Rimuovere il CSS render blocking in Next.js per Core Web Vitals migliori

Rimuovi il CSS render blocking in Next.js per Core Web Vitals più veloci

Arjen Karel Core Web Vitals Consultant
Arjen Karel - linkedin
Last update: 2026-03-09

Rimuovere il CSS render blocking in Next.js

Il CSS è render blocking. Il browser non dipingerà un singolo pixel finché non avrà scaricato e analizzato ogni foglio di stile all'interno dell'<head>. In un'app Next.js, questo significa due file CSS esterni per impostazione predefinita: un foglio di stile globale e uno specifico per la pagina. Su una connessione 3G veloce, scaricare questi due file ti costa 600ms prima che il browser inizi a renderizzare. Sono 600ms aggiunti direttamente al tuo First Contentful Paint e al Largest Contentful Paint.

Ultima revisione di Arjen Karel a Marzo 2026

In media, tra tutti i miei clienti e su tutti i dispositivi, misuro circa 200ms di ritardo causato dal CSS render blocking. Secondo il Web Almanac del 2025, l'85% delle pagine mobile non supera ancora l'audit delle risorse render blocking. La pagina mediana carica 8 file CSS per un totale di 79 KB. Su connessioni mobile lente, il ritardo di rendering può rappresentare il 69% del tempo totale di LCP. È il momento di risolvere il problema.

App Router vs Pages Router

La soluzione dipende da quale router di Next.js utilizzi. Il Pages Router (che utilizza _document.tsx) e l'App Router (che utilizza app/layout.tsx) gestiscono l'invio del CSS in modo diverso. L'inlining del CSS critico tramite critters non funziona con l'App Router perché lo streaming è incompatibile con il modo in cui critters elabora l'HTML. Se sei sull'App Router, passa direttamente all'Opzione 4.

L'App Router è l'impostazione predefinita da Next.js 13.4. Tuttavia, molte app in produzione utilizzano ancora il Pages Router, e le prime tre opzioni di seguito rimangono valide per queste ultime.

Opzione 1: Generare il CSS Critico (Pages Router)

L'opzione più veloce è generare il CSS Critico. Il CSS critico è un insieme di regole CSS necessarie per renderizzare la parte visibile della pagina. Queste regole vengono inserite inline nell'<head>. Successivamente, in parallelo, i file CSS originali vengono scaricati mentre il browser continua a renderizzare. Una volta scaricati i file CSS originali, vengono iniettati nella pagina.

Il CSS critico è disponibile in Next.js come funzionalità sperimentale. Aggiungi experimental: { optimizeCss: true } al tuo next.config.js. Next.js include internamente la libreria critters, quindi non hai bisogno di installarla separatamente. Nota che il pacchetto critters originale è deprecato (sostituito dal fork beasties), ma Next.js non ha ancora effettuato il passaggio.

const nextConfig = {
  reactStrictMode: true,
  experimental: { optimizeCss: true }
}

Questa opzione funziona solo con il Pages Router. Non supporta l'App Router perché critters necessita dell'intero HTML renderizzato, il che è incompatibile con lo streaming.

Opzione 2: Inline di tutto il CSS nell'head (Pages Router)

Se non vuoi abilitare le funzionalità sperimentali nella tua app Next.js, potresti considerare di inserire inline il tuo CSS manualmente. Crea una sezione head personalizzata e fai riferimento ad essa nel tuo _document.tsx.

Lo svantaggio è che il CSS inline sarà più grande rispetto al primo metodo, perché stai inserendo tutto inline, non solo le regole critiche. Tuttavia, se mantieni i tuoi fogli di stile puliti e leggeri, questo migliorerà significativamente i Core Web Vitals per la tua app Next.js.

import { Html, Head, Main, NextScript } from "next/document";
import { readFileSync } from "fs";
import { join } from "path";

class InlineStylesHead extends Head {
  getCssLinks: Head["getCssLinks"] = ({ allFiles }) => {
    const { assetPrefix } = this.context;
    if (!allFiles || allFiles.length === 0) return null;
    return allFiles
      .filter((file: any) => /\.css$/.test(file))
      .map((file: any) => (
        <style
          key={file}
          nonce={this.props.nonce}
          data-href={`${assetPrefix}/_next/${file}`}
          dangerouslySetInnerHTML={{
            __html: readFileSync(join(process.cwd(), ".next", file), "utf-8"),
          }}
        />
      ));
  };
}

export default function Document() {
  return (
    <Html>
      <InlineStylesHead />
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  );
}

Opzione 3: Styled Components (Pages Router)

Styled Components è uno strumento CSS-in-JS che ti consente di scrivere CSS all'interno di file JavaScript. Puoi limitare l'ambito dei nomi delle classi, rimuovere automaticamente il CSS inutilizzato e gestire gli stili insieme ai tuoi componenti. Per i Core Web Vitals, significa che vengono iniettati solo gli stili necessari in quella pagina.

Aggiungi compiler: { styledComponents: true } al tuo next.config.js, installa styled-components (yarn add styled-components e yarn add -D @types/styled-components), e poi aggiorna _document.js per supportare il rendering lato server per styled components.

const nextConfig = {
    reactStrictMode: true,
    compiler: {
    styledComponents: true,
  }
}
import Document, { DocumentContext } from "next/document";
import { ServerStyleSheet } from "styled-components";

export default class MyDocument extends Document {
  static async getInitialProps(ctx: DocumentContext) {
    const sheet = new ServerStyleSheet();
    const originalRenderPage = ctx.renderPage;

    try {
      ctx.renderPage = () =>
        originalRenderPage({
          enhanceApp: (App) => (props) =>
            sheet.collectStyles(<App {...props} />),
        });

      const initialProps = await Document.getInitialProps(ctx);
      return {
        ...initialProps,
        styles: (
          <>
            {initialProps.styles}
            {sheet.getStyleElement()}
          </>
        ),
      };
    } finally {
      sheet.seal();
    }
  }
}

Se utilizzi l'App Router con styled-components, hai bisogno di una configurazione diversa. Crea un componente client di registro degli stili utilizzando useServerInsertedHTML e avvolgi il tuo root layout con esso. Gli styled components funzionano solo nei Client Components all'interno dell'App Router. Consulta la guida CSS-in-JS di Next.js per il pattern completo.

Opzione 4: CSS Inline con inlineCss (App Router, Next.js 15+)

Per l'App Router, Next.js 15 ha introdotto experimental.inlineCss. Questo sostituisce tutti i tag di fogli di stile <link> con tag <style> inline, eliminando del tutto il waterfall render blocking.

const nextConfig = {
  experimental: {
    inlineCss: true,
  }
}

Questa funzionalità è ancora sperimentale e il team di Next.js non la consiglia ancora per la produzione. Inserisce inline tutto il CSS (non solo il CSS critico), il che aumenta la dimensione dell'HTML. Per i siti che utilizzano Tailwind CSS, questo compromesso funziona bene perché Tailwind genera bundle CSS piccoli e atomici. Per i siti con fogli di stile di grandi dimensioni, il gonfiore dell'HTML potrebbe penalizzare il Time to First Byte.

Una nota su CSS Modules e Tailwind CSS

CSS Modules e Tailwind CSS sono i due approcci di styling più popolari in Next.js oggi. Entrambi vengono compilati in file CSS standard in fase di build e sono serviti come tag <link>. Ciò significa che sono render blocking per impostazione predefinita.

Tailwind ha un vantaggio: poiché elimina le classi non utilizzate, l'output è tipicamente molto piccolo (spesso sotto i 10 KB gzipped). L'impatto render blocking di un file da 10 KB è minimo. I CSS Modules possono diventare più grandi se non si fa attenzione agli stili non utilizzati.

In ogni caso, tutte le opzioni precedenti sono applicabili. Se vuoi eliminare del tutto il CSS render blocking, combina il tuo approccio di styling preferito con optimizeCss (Pages Router) o inlineCss (App Router).

Quale opzione dovrei usare?

Dipende dal tuo router e dalla tua strategia CSS:

  • App Router + Tailwind: Usa inlineCss. I piccoli bundle CSS rendono pratico l'inlining.
  • App Router + CSS di grandi dimensioni: Attendi che inlineCss si stabilizzi, oppure usa una configurazione beasties personalizzata.
  • Pages Router: Usa optimizeCss (Opzione 1). È la soluzione più semplice e inserisce inline solo ciò che è critico.
  • Pages Router + CSS-in-JS: Usa styled-components o Emotion con i pattern SSR mostrati sopra.

Nei siti Next.js monitorati da CoreDash, quelli che utilizzano il CSS critico inlined mostrano un miglioramento mediano del FCP di 400ms rispetto alla distribuzione predefinita del CSS. Questa è la differenza tra un punteggio FCP buono e uno mediocre.

Qualunque opzione tu scelga, verifica i risultati con il Real User Monitoring. I punteggi di laboratorio (Lab) ti dicono cosa potrebbe accadere. I dati sul campo (Field) ti dicono cosa è effettivamente accaduto.

Per ulteriori informazioni su come il CSS e il JavaScript interagiscono con la pipeline di rendering, consulta la guida completa alla correzione delle risorse render blocking. Se stai ottimizzando un'app Next.js, controlla anche le guide su come risolvere il problema degli script di terze parti e su come misurare i Core Web Vitals in Next.js. Per uno sguardo più ampio alla strategia di caricamento, la guida alla prioritizzazione delle risorse tratta di come i browser decidono cosa scaricare per primo.

About the author

Arjen Karel is a web performance consultant and the creator of CoreDash, a Real User Monitoring platform that tracks Core Web Vitals data across hundreds of sites. He also built the Core Web Vitals Visualizer Chrome extension. He has helped clients achieve passing Core Web Vitals scores on over 925,000 mobile URLs.

Performance degrades unless you guard it.

I do not just fix the metrics. I set up the monitoring, the budgets, and the processes so your team keeps them green after I leave.

Start the Engagement
Rimuovere il CSS render blocking in Next.js per Core Web Vitals miglioriCore Web Vitals Rimuovere il CSS render blocking in Next.js per Core Web Vitals migliori