Remova o CSS de Bloqueio de Renderização no Next.js para Melhores Core Web Vitals

Remova o CSS de bloqueio de renderização no Next.js para Core Web Vitals mais rápidos

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

Remova o CSS de bloqueio de renderização no Next.js

O CSS bloqueia a renderização. O navegador não pintará um único pixel até que tenha baixado e analisado todas as folhas de estilo no <head>. Em um aplicativo Next.js, isso significa dois arquivos CSS externos por padrão: uma folha de estilo global e uma folha de estilo específica da página. Em uma conexão 3G rápida, o download desses dois arquivos custa 600ms antes mesmo do navegador começar a renderizar. São 600ms adicionados diretamente ao seu First Contentful Paint e Largest Contentful Paint.

Última revisão por Arjen Karel em março de 2026

Em média, em todos os meus clientes e todos os dispositivos, meço cerca de 200ms de atraso causado pelo CSS de bloqueio de renderização. De acordo com o Web Almanac de 2025, 85% das páginas mobile ainda falham na auditoria de recursos de bloqueio de renderização. A página mediana carrega 8 arquivos CSS totalizando 79 KB. Em conexões mobile lentas, o atraso de renderização pode representar 69% do tempo total do LCP. É hora de consertar isso.

App Router vs Pages Router

A correção depende de qual roteador do Next.js você utiliza. O Pages Router (usando _document.tsx) e o App Router (usando app/layout.tsx) lidam com a entrega de CSS de forma diferente. O inlining de critical CSS via critters não funciona com o App Router porque o streaming é incompatível com a forma como o critters processa o HTML. Se você estiver no App Router, pule para a Opção 4.

O App Router é o padrão desde o Next.js 13.4. Mas muitos aplicativos em produção ainda rodam o Pages Router, e as três primeiras opções abaixo continuam válidas para eles.

Opção 1: Gerar Critical CSS (Pages Router)

A opção mais rápida é gerar o critical CSS. O critical CSS é uma coleção de regras CSS necessárias para renderizar a parte visível da página. Essas regras são colocadas inline no <head>. Então, em paralelo, os arquivos CSS originais são baixados enquanto o navegador continua a renderizar. Uma vez que os arquivos CSS originais são baixados, eles são injetados na página.

O critical CSS está disponível no Next.js como um recurso experimental. Adicione experimental: { optimizeCss: true } ao seu next.config.js. O Next.js empacota a biblioteca critters internamente, então você não precisa instalá-la separadamente. Note que o pacote critters original está obsoleto (substituído pelo fork beasties), mas o Next.js ainda não fez a troca.

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

Esta opção funciona apenas com o Pages Router. Ela não suporta o App Router porque o critters precisa do HTML totalmente renderizado, o que é incompatível com o streaming.

Opção 2: Inserir todo o CSS inline no head (Pages Router)

Se você não quiser habilitar recursos experimentais no seu aplicativo Next.js, você pode considerar colocar seu CSS inline manualmente. Crie uma seção head personalizada e referencie-a no seu _document.tsx.

A desvantagem é que o CSS inline será maior do que com o primeiro método porque você está colocando tudo inline, não apenas as regras críticas. No entanto, se você mantiver suas folhas de estilo limpas e enxutas, isso melhorará os Core Web Vitals do seu aplicativo Next.js significativamente.

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>
  );
}

Opção 3: Styled Components (Pages Router)

O Styled Components é uma ferramenta CSS-in-JS que permite escrever CSS em arquivos JavaScript. Você pode criar escopos para nomes de classes, remover CSS não utilizado automaticamente e gerenciar estilos junto com seus componentes. Para os Core Web Vitals, isso significa que apenas os estilos necessários naquela página são injetados.

Adicione compiler: { styledComponents: true } ao seu next.config.js, instale o styled-components (yarn add styled-components e yarn add -D @types/styled-components), e em seguida, atualize o _document.js para suportar a renderização no lado do servidor para 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 você usa o App Router com styled-components, você precisa de uma configuração diferente. Crie um client component de registro de estilo usando useServerInsertedHTML e envolva seu root layout com ele. Os styled components funcionam apenas em Client Components no App Router. Veja o guia de CSS-in-JS do Next.js para o padrão completo.

Opção 4: CSS Inline com inlineCss (App Router, Next.js 15+)

Para o App Router, o Next.js 15 introduziu o experimental.inlineCss. Isso substitui todas as tags de folha de estilo <link> por tags <style> inline, eliminando totalmente a cascata de bloqueio de renderização.

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

Isso ainda é experimental e a equipe do Next.js ainda não recomenda para produção. Ele coloca todo o CSS inline (não apenas o critical CSS), o que aumenta o tamanho do HTML. Para sites usando Tailwind CSS, essa troca funciona bem porque o Tailwind gera pacotes CSS pequenos e atômicos. Para sites com grandes folhas de estilo, o inchaço do HTML pode prejudicar o Time to First Byte.

Uma observação sobre CSS Modules e Tailwind CSS

CSS Modules e Tailwind CSS são as duas abordagens de estilização mais populares no Next.js hoje. Ambos compilam para arquivos CSS padrão no momento da build e são servidos como tags <link>. Isso significa que eles bloqueiam a renderização por padrão.

O Tailwind tem uma vantagem: como ele expurga classes não utilizadas, o output é tipicamente muito pequeno (frequentemente menos de 10 KB compactado com gzip). O impacto de bloqueio de renderização de um arquivo de 10 KB é mínimo. Os CSS Modules podem crescer mais se você não tomar cuidado com os estilos não utilizados.

De qualquer forma, todas as opções acima se aplicam. Se você quiser eliminar totalmente o CSS de bloqueio de renderização, combine sua abordagem de estilização preferida com optimizeCss (Pages Router) ou inlineCss (App Router).

Qual opção devo usar?

Isso depende do seu roteador e da sua estratégia de CSS:

  • App Router + Tailwind: Use inlineCss. Pacotes CSS pequenos tornam a inserção inline prática.
  • App Router + CSS grande: Aguarde a estabilização do inlineCss ou use uma configuração personalizada do beasties.
  • Pages Router: Use optimizeCss (Opção 1). É a correção mais simples e coloca inline apenas o que é crítico.
  • Pages Router + CSS-in-JS: Use styled-components ou Emotion com os padrões de SSR mostrados acima.

Em sites Next.js monitorados pelo CoreDash, aqueles que usam critical CSS inline apresentam uma melhoria mediana de FCP de 400ms em comparação com a entrega padrão de CSS. Essa é a diferença entre uma pontuação de FCP boa e uma medíocre.

Seja qual for a opção que você escolher, verifique os resultados com o Real User Monitoring. As pontuações de laboratório dizem o que pode acontecer. Os dados de campo dizem o que realmente aconteceu.

Para saber mais sobre como o CSS e o JavaScript interagem com o pipeline de renderização, veja o guia completo para consertar recursos de bloqueio de renderização. Se você estiver otimizando um aplicativo Next.js, verifique também os guias sobre como consertar scripts de terceiros e como medir os Core Web Vitals no Next.js. Para uma visão mais ampla sobre a estratégia de carregamento, o guia de priorização de recursos aborda como os navegadores decidem o que buscar primeiro.

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.

Dados em tempo real. Nada de média de 28 dias.

CoreDash segmenta cada métrica por rota, aparelho, browser e tipo de conexão.

Dá uma olhada no CoreDash
Remova o CSS de Bloqueio de Renderização no Next.js para Melhores Core Web VitalsCore Web Vitals Remova o CSS de Bloqueio de Renderização no Next.js para Melhores Core Web Vitals