Uma landing page pode carregar um único arquivo CSS e ainda obrigar o navegador a esperar por regras que pertencem ao rodapé, ao modal fechado e a páginas que nem estão abertas.

CSS bloqueia a renderização por um bom motivo: mostrar a página antes dos estilos pode produzir conteúdo quebrado ou um flash sem formatação. O problema não é ter CSS. É colocar trabalho demais no caminho da primeira pintura.

Sites criados por IA acumulam esse custo quando prompts sucessivos adicionam componentes, copiam temas inteiros e deixam estados antigos no arquivo. A correção começa com evidência por rota e termina com uma revisão visual, não com uma porcentagem isolada de código sem uso.

Entenda o que bloqueia a renderização

Ao encontrar uma folha declarada com rel="stylesheet", o navegador precisa baixar e analisar o arquivo antes de montar a árvore de renderização. Uma folha grande ou uma cadeia de imports pode atrasar o conteúdo mesmo quando o HTML e a imagem principal já chegaram.

O material do web.dev sobre caminho crítico de renderização descreve CSS como bloqueante por padrão. Isso não significa que todo seletor do arquivo seja necessário na primeira tela.

Separe três grupos:

Grupo Exemplo Tratamento inicial
crítico layout, tipografia e cores visíveis na primeira tela carregar antes da primeira pintura
necessário depois FAQ, modal, rodapé, estados acionados por interação dividir ou adiar com cuidado
sem uso componente removido, variante antiga, biblioteca não utilizada excluir depois de confirmar todos os estados

O tamanho transferido importa, mas também conte requisições, dependências e tempo de análise. Um arquivo comprimido pode continuar bloqueante.

Meça uma rota e um cenário por vez

Abra a página publicada no Chrome DevTools e registre:

URL e versão:
largura e dispositivo:
folhas carregadas:
bytes transferidos e não comprimidos:
requisições bloqueantes:
tempo da primeira pintura e do LCP:
regras sem uso no cenário:

No painel Performance, a seção de insights mostra requisições que bloqueiam a renderização e a árvore de dependências. Na aba Network, filtre por CSS e confira Initiator, prioridade e ordem.

O painel Coverage do Chrome DevTools marca as faixas de CSS usadas e não usadas durante a gravação. Comece a gravação, recarregue a página e percorra os estados relevantes.

Não leia 70% de vermelho como “apague 70%”. Coverage descreve somente aquela execução. Uma regra de modal, hover, validação, breakpoint ou impressão pode ser necessária sem aparecer no carregamento inicial.

Exercite os estados antes de remover regras

Monte uma matriz curta para cada rota:

  • celular, tablet e desktop;
  • menu fechado e aberto;
  • campos vazios, inválidos, carregando, sucesso e erro;
  • modal, FAQ e dropdown abertos;
  • banner de consentimento em cada decisão;
  • foco por teclado e :focus-visible;
  • tema ou preferência de movimento, quando existirem;
  • página impressa, se o produto promete impressão;
  • conteúdo curto, longo e traduzido.

Faça uma captura ou teste visual antes da alteração. O checklist de QA para landing pages ajuda a cobrir comportamento além da primeira dobra.

Classes montadas dinamicamente merecem atenção. Ferramentas de remoção podem não enxergar um nome construído em JavaScript:

element.className = `badge badge-${status}`;

Prefira um mapa explícito quando o build precisa encontrar as variantes:

const statusClass = {
error: "badge badge-error",
pending: "badge badge-pending",
success: "badge badge-success",
};

Se o framework usa uma safelist, mantenha-a pequena e documente qual estado exige cada padrão.

Remova fontes inteiras de CSS sem uso

Excluir regras uma por uma costuma deixar o mecanismo que gerou o excesso intacto. Procure primeiro por blocos maiores:

  • tema ou reset duplicado;
  • biblioteca de componentes sem consumidores;
  • estilos copiados de outra rota;
  • versão antiga de um componente;
  • utilitários gerados para caminhos que a build não escaneia direito;
  • CSS de plugin removido;
  • imports globais feitos dentro de vários componentes;
  • variantes de campanha encerrada.

Use busca por classes, atributos e imports no código-fonte. Depois remova um bloco, rode a build e percorra a matriz visual. Mudanças pequenas tornam a regressão localizável.

Minificação não substitui exclusão. Ela reduz a representação dos seletores, mas o navegador ainda recebe e analisa regras que não participam da página.

Divida CSS por rota e componente

Uma folha global deve conter o que realmente é global: tokens, base tipográfica, reset necessário e padrões compartilhados por muitas rotas.

Estilos de uma calculadora, dashboard ou modal específico podem acompanhar o componente ou a rota. O mecanismo exato depende da build, então valide o HTML produzido e a aba Network. Um import dentro do componente não garante divisão se o bundler decidir consolidar tudo.

Evite fragmentar até criar dezenas de arquivos minúsculos no caminho crítico. O objetivo é impedir que a home baixe estilos de áreas que não usa, mantendo poucas dependências previsíveis.

Registre a decisão:

global.css: base, tokens e padrões compartilhados
home.css: hero, prova social e CTA da home
pricing.css: cards e comparação de planos
dialog.css: carregado com o componente de diálogo

Mantenha o CSS crítico pequeno

Inserir estilos críticos em um bloco style no HTML elimina uma requisição antes da primeira pintura. A troca tem custo: CSS inline aumenta cada documento e não aproveita o cache de uma folha externa em navegações seguintes.

A orientação atual para otimizar LCP recomenda inline somente quando o conjunto é pequeno. Para uma folha grande, reduza o arquivo e adie o que não participa da primeira tela.

Se adotar CSS crítico:

  1. extraia apenas o necessário para o conteúdo inicial de cada rota;
  2. mantenha o restante em uma folha cacheável;
  3. evite duplicar as mesmas regras nos dois lugares;
  4. teste páginas com conteúdo e breakpoints diferentes;
  5. verifique se a build atualiza o bloco quando o componente muda.

Não cole manualmente um snapshot que ficará desconectado do código-fonte. Uma extração desatualizada produz divergência visual e aumenta o custo de manutenção.

Adie somente o que não afeta a primeira tela

Uma folha de impressão pode declarar sua condição sem bloquear a tela:

<link rel="stylesheet" href="/assets/print.css" media="print" />

Condições de mídia reais ajudam o navegador a priorizar o recurso para o contexto correto. Não use media="print" como truque temporário para carregar qualquer CSS e trocar o atributo com JavaScript. Se o script falhar ou atrasar, a página perde estilos.

Para conteúdo aberto por interação, avalie carregar o CSS junto do componente. Preserve um estado básico funcional enquanto o recurso chega e teste teclado, foco e leitores de tela.

Não adie regras da hero, do título, do menu visível ou do botão principal. Um LCP mais cedo com layout quebrado não é uma melhora de produto.

Corte cadeias de @import

Um @import dentro de uma folha só pode ser descoberto depois que o navegador recebe e analisa o arquivo anterior.

@import url("./tokens.css");
@import url("./components.css");

Quando essas folhas são críticas, deixe a build consolidá-las ou declare recursos independentes diretamente no HTML. Confirme no waterfall se existe uma cadeia serial antes de alterar.

Não transforme todo import em preload. Preload inicia transferências mesmo quando a rota não precisa delas. Remova a dependência ou deixe a build gerar a divisão correta.

Comprima depois de corrigir a estrutura

Depois de excluir e dividir:

  • minifique o CSS de produção;
  • confirme Brotli ou gzip na resposta pública;
  • use nomes versionados quando o conteúdo muda;
  • mantenha mapas de fonte fora da entrega pública quando não forem necessários;
  • compare bytes transferidos, bytes analisados e requisições bloqueantes.

O guia de compressão Brotli e gzip mostra como verificar Content-Encoding sem confundir o tamanho do arquivo local com a resposta entregue.

Compressão reduz rede. Remoção reduz rede e trabalho do navegador. Divisão evita enviar estilos de outra rota. São efeitos diferentes.

Preserve fontes, layout e interação

CSS aparentemente sem uso pode controlar um estado raro e importante.

Depois da mudança, teste:

  • fonte de fallback e fonte carregada;
  • dimensões reservadas para imagens e embeds;
  • foco visível e contraste;
  • hover, active, disabled e loading;
  • mensagens longas de validação;
  • zoom de 200%;
  • larguras próximas aos breakpoints;
  • conteúdo sem JavaScript, quando houver fallback prometido.

Use o guia de fontes web para evitar troca de métrica. Remover uma regra pode reduzir CSS e ao mesmo tempo criar layout shifts.

Republique como uma Version coerente

No Site no Ar, a página pública recebe os arquivos dentro de public/. HTML com referências novas e CSS com nome versionado precisam entrar no mesmo deploy.

  1. chame get_context antes de editar;
  2. inspecione HTML, CSS e imports com as file tools;
  3. remova ou divida as regras no código-fonte;
  4. rode build, testes e a matriz visual;
  5. atualize todos os arquivos gerados dentro de public/;
  6. mantenha public/sitemap.xml correto;
  7. chame deploy e acompanhe deploy_status;
  8. repita Coverage e Performance na URL publicada.

A documentação de Publicação explica como uma nova Version substitui o conteúdo servido. Não avalie apenas a build local: cache, compressão e headers fazem parte da resposta final.

Mantenha o mesmo Site e a mesma URL para comparar versões. O fluxo de republicação com agente de IA preserva essa continuidade.

Prompt para revisar CSS bloqueante

Revise o CSS desta página sem publicar ainda.
URL e versão: [URL e commit]
Rotas: [lista]
Estados obrigatórios: [menu, formulário, modal, temas e breakpoints]
1. Liste as folhas e a árvore de dependências da rota.
2. Grave Performance e Coverage durante todos os estados informados.
3. Separe CSS crítico, necessário depois e sem uso.
4. Remova primeiro imports, temas e componentes sem consumidores.
5. Divida por rota sem criar uma cadeia de requisições críticas.
6. Preserve foco, fontes, layout, impressão e conteúdo responsivo.
7. Rode build e testes visuais e compare LCP, bytes e requisições.

O resultado esperado não é um arquivo com a menor porcentagem possível. É uma primeira renderização com poucas dependências, seguida por todos os estados visuais que a página ainda precisa cumprir.