Como remover CSS e JS que bloqueiam renderização

Como remover CSS e JS que bloqueiam renderização

Última verificação: 13 de outubro de 2026
17 min de leitura
Guia
Core Web Vitals

Quando o navegador carrega a sua página, lê o código HTML linha a linha. Quando encontra <script src="ficheiro-grande.js"> ou <link rel="stylesheet">, para tudo o resto, descarrega o ficheiro e executa-o.

Só depois renderiza o resto da página. Isto é “Render-Blocking” (Bloqueio de Renderização).

Em 2026, quando os Core Web Vitals importam (especialmente LCP - Largest Contentful Paint), tem de corrigir isto.

#Como o navegador renderiza uma página

Para perceber porque certos ficheiros travam a renderização, convém olhar para a ordem em que o navegador constrói uma página.

#Como o navegador constrói o DOM e o CSSOM

  1. Descarga do HTML. O navegador descarrega o documento HTML do servidor.
  2. Parsing do HTML. O parser percorre o HTML linha a linha e constrói o DOM (Document Object Model), a estrutura em árvore da página.
  3. Encontro com CSS. Quando o parser encontra <link rel="stylesheet">, tem de descarregar e processar esse ficheiro para construir o CSSOM (CSS Object Model). Até lá a renderização fica parada, porque sem estilos o navegador não sabe como pintar os elementos. Como resume o web.dev, o navegador tem de descarregar e analisar os ficheiros CSS antes de mostrar a página, e isso faz do CSS um recurso que bloqueia a renderização.
  4. Encontro com JavaScript. Perante <script src="..."> sem atributos, o parser para por completo. Descarrega o ficheiro, analisa-o e executa-o, e só depois continua com o resto do HTML. Isto acontece porque o JavaScript pode alterar o DOM que está a ser construído.
  5. Render Tree. Só quando o DOM e o CSSOM estão prontos é que o navegador os combina na Render Tree e pinta a página.

Cada ficheiro CSS ou JavaScript no <head> sem atributos especiais trava este processo. Com 5 ficheiros CSS e 8 scripts no head, o navegador tem de descarregar e processar os 13 antes de mostrar um único píxel ao utilizador.

#Como o bloqueio da renderização afeta os Core Web Vitals

O bloqueio da renderização afeta diretamente duas métricas:

FCP (First Contentful Paint): o momento em que o navegador pinta o primeiro conteúdo (texto, imagem, SVG). Quanto mais recursos bloquearem, mais tarde isso acontece. O objetivo é um FCP inferior a 1,8 segundos.

LCP (Largest Contentful Paint): o momento em que o maior elemento visível no ecrã fica renderizado. Se um ficheiro CSS pesado impede o navegador de pintar a imagem hero ou o bloco de texto principal, o LCP dispara. O objetivo é um LCP inferior a 2,5 segundos.

No WordPress, cada plugin pode colocar em fila a sua própria folha de estilos e o seu próprio script em todas as páginas, incluindo as que não os usam, e a lista do PageSpeed Insights cresce com cada plugin instalado. Enquanto esses ficheiros não chegam, o visitante vê um ecrã em branco. No telemóvel cada pedido demora mais por causa da latência da rede, e o mesmo número de ficheiros custa mais tempo do que no computador.

#Async e defer em JavaScript no WordPress

A velha guarda dizia: “meta scripts no rodapé (wp_footer)”. A nova guarda diz: “use atributos”.

  • <script async>: Descarrega em segundo plano, executa imediatamente após download (arriscado para dependências, ex: jQuery).
  • <script defer>: Descarrega em segundo plano, executa só após HTML carregado (seguro, preserva ordem).

Como adicionar defer no WordPress? Plugins de cache (WP Rocket, Autoptimize, LiteSpeed Cache) têm opção “Defer JS”. Ative-a.

Depois de a ativar, verifique a consola do navegador nas páginas com sliders, formulários e galerias.

#O que é Critical CSS e como usar

CSS é mais difícil. Não pode “atrasar” porque a página vai parecer “texto cru” por um momento (sem estilos - efeito FOUC).

A solução é Critical CSS.

  1. Pegue apenas no CSS necessário para mostrar conteúdo “acima da dobra” (visível sem scroll).
  2. Cole-o inline em <style> no header.
  3. Carregue o resto do CSS (rodapé, secções inferiores) de forma assíncrona em segundo plano.

A maioria dos plugins de otimização modernos gera Critical CSS automaticamente.

#Resumo da estratégia

  1. JS: Tudo com defer (exceto scripts absolutamente críticos de analytics/cookies). Nunca async em scripts que dependem do jQuery.
  2. CSS: Critical CSS inline por tipo de página (início, artigo, produto, categoria) + resto assíncrono.
  3. Fontes: Alojadas localmente, em WOFF2, com font-display: swap e preload da fonte principal.
  4. Imagens: A imagem LCP com fetchpriority="high", as restantes com lazy loading nativo.
  5. Terceiros: Analytics, chat e widgets sociais com defer ou só depois de uma interação do utilizador.
  6. Minificação: Todos os ficheiros CSS e JS minificados, combinados apenas quando isso comprovadamente ajuda.

Assim, o utilizador vê conteúdo imediatamente enquanto scripts pesados de galerias ou mapas carregam em segundo plano.

#Como identificar recursos que bloqueiam a renderização

O relatório do Lighthouse lista os ficheiros bloqueadores, mas não diz que parte deles é realmente usada. Abra as DevTools, corra “Show Coverage” a partir da paleta de comandos e recarregue. A coluna “Unused Bytes” separa dois problemas muito diferentes: CSS a mais, ou CSS carregado no momento errado. Se a maior parte de um ficheiro não é usada naquela página, minificar não resolve nada de relevante. A documentação do Lighthouse recomenda o separador Coverage precisamente para encontrar CSS e JS não críticos.

Depois vá ao separador Network e procure ficheiros pequenos que começam a descarregar tarde. São quase sempre recursos que o navegador só descobriu depois de processar outro ficheiro, e são esses, e só esses, que justificam um preload.

O Lighthouse marca como bloqueante um <script> no <head> sem defer nem async, e um <link rel="stylesheet"> sem atributo disabled cujo media corresponde ao dispositivo. media="all" conta como bloqueante.

#Detetar bloqueios com o PageSpeed Insights

O PageSpeed Insights lista os ficheiros em causa em “Eliminar recursos que bloqueiam a renderização”. Para cada um mostra o URL, o tamanho e a poupança potencial em milissegundos, o que dá uma lista de trabalho ordenada por impacto.

#Detetar bloqueios com o WebPageTest

O WebPageTest mostra um waterfall detalhado em que cada pedido aparece dividido em DNS, ligação, TLS e descarga. Procure os ficheiros CSS e JS que terminam antes da linha vertical de Start Render: foram esses que o navegador esperou antes de pintar.

#Diferença entre async e defer

AtributoDescargaExecuçãoMantém a ordemIndicado para
nenhumbloqueia o parsingimediatasimevitar sempre no <head>
asyncparalelaassim que o ficheiro cheganãoscripts isolados, sem dependências
deferparaleladepois do HTML processadosimtudo o que depende de jQuery ou de outro script
type="module"paraleladepois do parsingsimmódulos ES, já trazem defer

Na prática, defer é a escolha por omissão e async é a excepção. O motivo é simples: com async os ficheiros executam pela ordem em que calham ficar prontos. Uma galeria que chame jQuery(...) antes de o jQuery estar carregado devolve um TypeError na consola e uma galeria vazia na página. No computador de quem desenvolve isto raramente aparece, porque está tudo em cache e chega na ordem certa por acaso.

Dois detalhes da referência do MDN evitam surpresas. defer e async não têm efeito em scripts inline sem src. E os scripts com type="module" já são adiados por omissão, por isso acrescentar defer não muda nada. Os scripts adiados executam antes do evento DOMContentLoaded, e um fragmento inline que precise de jQuery adiado pode esperar por esse evento.

#Defer no WordPress sem plugin

O WordPress 6.3 acrescentou o argumento strategy ao wp_enqueue_script(), e é hoje a forma correcta de o fazer, porque é o próprio WordPress a validar a cadeia de dependências:

wp_enqueue_script(
    'tema-galeria',
    get_template_directory_uri() . '/js/galeria.js',
    array( 'jquery' ),
    '1.2.0',
    array(
        'in_footer' => true,
        'strategy'  => 'defer',
    )
);

Declarar a dependência é o que dá valor ao bloco, porque o WordPress verifica a cadeia antes de imprimir o atributo. A nota de desenvolvimento do WordPress 6.3 define as regras: para um script ser adiado, as suas dependências podem ser adiadas ou bloqueantes, mas todos os scripts que dependem dele têm de ser adiados. Se algum deles for bloqueante, o script e as suas dependências voltam a carregar de forma bloqueante. Um script async pode descer para defer ou para bloqueante, nunca o contrário. E se lhe juntar código inline na posição after com wp_add_inline_script(), a estratégia é removida. Uma galeria adiada com jQuery bloqueante é portanto permitida, porque o jQuery corre primeiro de qualquer forma.

Para scripts de um plugin, a mesma nota indica wp_script_add_data( $handle, 'strategy', 'defer' ), chamado depois de o plugin registar o handle. Versões anteriores à 6.3 simplesmente ignoram a chave. Desde o WordPress 6.9, segundo a referência da função, o mesmo array aceita também a chave fetchpriority.

Para instalações mais antigas, ou para um plugin que não pode alterar, resta o filtro:

add_filter( 'script_loader_tag', 'pt_defer_scripts_escolhidos', 10, 2 );

function pt_defer_scripts_escolhidos( string $tag, string $handle ): string {
    $adiados = array( 'slider', 'lightbox', 'mapa' );

    return in_array( $handle, $adiados, true )
        ? str_replace( ' src', ' defer src', $tag )
        : $tag;
}

Repare no sentido da lista. É uma lista de permissões, não de exclusões. Uma lista de exclusões (“tudo menos estes”) passa também a adiar qualquer script que o próximo plugin instalado venha a registar, e aí tem um defeito que não escreveu.

#Como carregar CSS e JS de plugins só nas páginas onde são usados

Antes de adiar, pergunte se aquilo precisa sequer de ser carregado naquela página. Um plugin de formulários carrega CSS e JS em todo o site por causa de um formulário que existe apenas na página de contacto:

add_action( 'wp_enqueue_scripts', 'pt_assets_do_formulario_so_no_contacto', 99 );

function pt_assets_do_formulario_so_no_contacto(): void {
    if ( ! is_page( 'contacto' ) ) {
        wp_dequeue_style( 'contact-form-7' );
        wp_dequeue_script( 'contact-form-7' );
    }
}

O teste que falta quase sempre a seguir a este bloco: submeter o formulário depois da alteração. Se o site tiver formulários embebidos noutro sítio, por exemplo um pedido de marcação no rodapé, a condição is_page remove os assets exactamente onde eram precisos e o formulário deixa de enviar sem dar erro visível.

O mesmo vale para as folhas de estilo do WooCommerce, que só fazem falta nas páginas da loja:

add_action( 'wp_enqueue_scripts', 'pt_css_da_loja_so_na_loja', 100 );

function pt_css_da_loja_so_na_loja(): void {
    if ( function_exists( 'is_woocommerce' ) && ! is_woocommerce() && ! is_cart() && ! is_checkout() ) {
        wp_dequeue_style( 'woocommerce-general' );
        wp_dequeue_style( 'woocommerce-layout' );
        wp_dequeue_style( 'woocommerce-smallscreen' );
    }
}

Ferramentas como o PurgeCSS ou o UnCSS vão mais longe e removem, dentro de cada ficheiro, os seletores que não aparecem na página. Isso reduz o que o navegador tem de descarregar e analisar, mas traz o risco descrito mais abaixo nos erros comuns.

#Carregar CSS de forma assíncrona sem FOUC

O padrão é sempre o mesmo: o CSS crítico embutido no <head> e o resto carregado sem bloquear.

<style>/* apenas as regras do que se vê sem scroll */</style>
<link rel="preload" href="/style.css" as="style"
      onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="/style.css"></noscript>

A linha noscript não é decoração. Sem ela, quem tem JavaScript desactivado fica sem folha de estilos nenhuma, e isso inclui redes empresariais com filtragem de conteúdos.

O padrão com preload e onload é o que o web.dev recomenda para CSS não crítico.

Há três coisas que decidem o resultado. O tamanho: o guia do web.dev sobre CSS crítico recomenda manter o conteúdo acima da dobra abaixo de 14 KB comprimidos, para reduzir as viagens de ida e volta até à primeira renderização. Acima disso passa a pagar uma resposta HTML maior em cada visita e apenas mudou o problema de sítio. O viewport: CSS crítico gerado a 1300 pixéis de largura não conhece as regras exclusivas de telemóvel, por isso gere para as duas larguras e junte o resultado. E o teste em ligação lenta: ponha as DevTools em “Slow 3G” e recarregue. Se vir texto sem estilos durante meio segundo antes de o layout encaixar, falta conteúdo no bloco crítico.

#Gerar Critical CSS: ferramentas e plugins

O mesmo guia do web.dev cita duas ferramentas. A Critical extrai, minifica e embute o CSS acima da dobra e funciona com Gulp, Grunt ou webpack. O Penthouse serve para sites com muitos estilos ou estilos injetados dinamicamente, mas não deteta as folhas de estilo sozinho: é o utilizador que indica os ficheiros HTML e CSS.

No WordPress, o trabalho fica normalmente a cargo de plugins:

WP Rocket: Na opção “Otimizar a entrega de CSS”, gera Critical CSS para cada página e embute-o inline.

Autoptimize com CriticalCSS.com: O Autoptimize liga-se ao serviço CriticalCSS.com. Precisa de uma chave de API, e a partir daí a geração é automática.

LiteSpeed Cache: Gera Critical CSS através do serviço QUIC.cloud, e a cache de página funciona em servidores LiteSpeed.

Perfmatters: Um plugin leve cujo Script Manager desativa scripts e estilos por página, útil para plugins que carregam os seus ficheiros em todo o site.

#Font-display swap e preload de fontes

Uma fonte própria sem font-display provoca FOIT: o navegador esconde o texto até o ficheiro chegar. Numa ligação móvel fraca são vários segundos de área em branco onde devia estar o conteúdo.

@font-face {
    font-family: 'Inter';
    src: url('/fonts/inter.woff2') format('woff2');
    font-display: swap;
}

Com swap, o texto aparece de imediato na fonte do sistema e troca quando o ficheiro chega. Junte um preload, com crossorigin, que é exigido para fontes mesmo quando o ficheiro está no seu próprio domínio:

<link rel="preload" href="/fonts/inter.woff2" as="font" type="font/woff2" crossorigin>

Alojar a fonte no próprio servidor poupa ainda uma resolução de DNS e um handshake TLS contra um domínio externo antes de a descarga começar sequer.

Há também a questão da privacidade. O carregamento dinâmico do Google Fonts envia o endereço IP do visitante para servidores da Google. Em janeiro de 2022, o Landgericht München I, um tribunal alemão, considerou ilícita essa transmissão sem consentimento, e a sentença deu origem a uma vaga de reclamações na Alemanha.

Para alojar o Google Fonts localmente:

  1. Descarregue os ficheiros de fonte a partir do repositório do Google Fonts ou com a ferramenta google-webfonts-helper.
  2. Envie os ficheiros WOFF2 para o seu servidor, porque o WOFF2 oferece a melhor compressão.
  3. Atualize as regras @font-face no CSS para apontarem para os ficheiros locais.
  4. Remova do HTML as referências a fonts.googleapis.com e fonts.gstatic.com.

No WordPress, o plugin OMGF (Optimize My Google Fonts) automatiza todo este processo.

#Minificar e combinar CSS e JS com HTTP/2

#O que a minificação traz

A minificação remove espaços, comentários e caracteres desnecessários dos ficheiros CSS e JavaScript sem alterar o seu funcionamento. A poupança depende de quantos comentários e espaços o ficheiro original tem, e com gzip ou Brotli ativos no servidor a diferença transferida é menor do que a do ficheiro sem compressão.

No WordPress, a minificação fica normalmente a cargo dos plugins de cache: o WP Rocket minifica CSS e JS com uma caixa de verificação, o Autoptimize é especializado em minificar e combinar ficheiros, e o LiteSpeed Cache inclui minificação integrada.

#Combinar ficheiros CSS e JS com HTTP/2

Juntar vários ficheiros CSS num só (e vários ficheiros JS num só) reduz o número de pedidos HTTP. Com HTTP/2 e HTTP/3 isto pesa menos do que antes, porque estes protocolos permitem várias descargas em simultâneo numa só ligação.

Combinar pode até ser contraproducente se invalidar a cache com demasiada frequência. Se juntar 15 ficheiros CSS num só e um plugin mudar uma única linha, o ficheiro combinado inteiro tem de ser descarregado de novo. Com ficheiros separados, só o ficheiro alterado precisa de ser atualizado.

A recomendação atual é minificar sempre, mas combinar apenas quando o site ainda usa HTTP/1.1 ou quando o waterfall mostra dezenas de ficheiros pequenos à espera da sua vez.

#Preload, prefetch e fetchpriority no WordPress

Além de async, defer e Critical CSS, os navegadores modernos aceitam indicações de prioridade que dizem que recursos são críticos e quais podem esperar.

#Quando usar preload

<link rel="preload" href="/critical-script.js" as="script">
<link rel="preload" href="/imagem-hero.webp" as="image">

O preload diz ao navegador para descarregar um recurso o mais cedo possível, antes de o descobrir naturalmente durante o parsing do HTML. Use-o para recursos críticos como a imagem LCP, a fonte principal ou um script essencial.

#Quando usar prefetch

<link rel="prefetch" href="/pagina-seguinte/">
<link rel="prefetch" href="/estilos-pagina2.css">

O prefetch descarrega um recurso com prioridade baixa nos tempos mortos, antecipando que o utilizador vai precisar dele em breve. É útil para recursos da página seguinte mais provável.

#Quando usar fetchpriority

<img src="/hero.webp" fetchpriority="high">
<img src="/decorativa.webp" fetchpriority="low">

O atributo fetchpriority ajusta a prioridade de descarga de recursos individuais: mais alta para a imagem LCP, mais baixa para imagens decorativas ou fora do ecrã. Segundo o web.dev, funciona em link, img e script com os valores high, low e auto. Preload e fetchpriority fazem trabalhos diferentes: o preload serve para o navegador descobrir o recurso mais cedo, o fetchpriority muda a prioridade mas não ajuda a descobri-lo. Uma imagem LCP com preload pode continuar a receber prioridade baixa, e uma imagem de fundo em CSS que seja o elemento LCP continua a precisar de preload.

#Como atrasar scripts de terceiros e widgets de chat

Pode optimizar o seu tema ao detalhe e continuar preso no mesmo LCP porque um widget de conversação e um mapa embebido trazem algumas centenas de kilobytes cada um. Carregue o widget só quando houver sinal de presença do utilizador:

addEventListener('scroll', function carregar() {
    const s = document.createElement('script');
    s.src = 'https://widget.example.com/chat.js';
    s.defer = true;
    document.body.appendChild(s);
}, { once: true });

Ninguém abre uma conversa nos primeiros 300 milissegundos, por isso não há nada a perder em esperar.

Para mapas e vídeos use uma fachada: uma imagem estática com o aspecto do player ou do mapa, e o iframe verdadeiro apenas ao clique. É o caso típico de um restaurante ou de uma clínica que embebe o mapa da morada no rodapé de todas as páginas, quando esse mapa só interessa a uma minoria das visitas. O pacote lite-youtube-embed faz exactamente isto para o YouTube e reduz a incorporação de centenas de kilobytes para poucos.

#Lighthouse ou dados de campo no Search Console para render blocking

O Lighthouse são dados de laboratório e servem para ter resposta rápida a cada alteração. O que aparece na Search Console são dados de campo do Chrome User Experience Report. Não se contradizem, medem coisas diferentes: uma medição num aparelho contra uma janela deslizante de 28 dias sobre aparelhos e ligações reais.

A consequência prática interessa: se a Search Console estiver na mesma no dia seguinte ao deploy, isso não é um resultado, é a janela ainda não ter rodado. Registe a data da publicação, senão daqui a um mês já ninguém consegue dizer que parte da curva pertence a que alteração.

#Erros comuns ao adiar CSS e JS

  • async em algo que depende do jQuery. Galerias vazias e formulários que não enviam, e só em ligações lentas.
  • CSS embutido a mais. Acima de 14 KB comprimidos, cada visita paga a conta.
  • Purgar CSS sem verificação visual. As ferramentas automáticas podem remover estilos que só se ativam com interação (hover, estados ativos, modais) ou que se aplicam a conteúdo carregado dinamicamente. Verifique sempre o resultado, sobretudo no telemóvel.
  • Testar só no computador. Um site pode carregar depressa numa ligação de fibra e falhar no telemóvel com 4G. Teste na vista móvel do PageSpeed Insights e em aparelhos reais.
  • Perseguir os 100 pontos. O PageSpeed Insights é uma ferramenta de diagnóstico, não um objetivo. Otimize para a experiência real de quem visita, não para um número.
  • Esquecer o viewport móvel no Critical CSS. É no telemóvel que se faz a medição que conta.
  • Lista de exclusões em vez de lista de permissões ao adiar scripts. O próximo plugin passa a ser problema seu.
  • Não voltar a verificar depois de actualizar plugins. Os plugins mudam o que registam, e uma configuração que funcionava no ano passado pode estar partida em silêncio hoje.

Veja os nossos serviços de otimização de velocidade WordPress.

Próximo passo

Transforme o artigo numa implementação real

Este bloco reforça a ligação interna e conduz o leitor para o passo seguinte mais útil dentro da arquitetura do site.

Quer implementar isto no seu site?

Se o problema está nos Core Web Vitals, no rendering lento ou no peso do WordPress, posso mapear e implementar a otimização.

Cluster relacionado

Explorar outros serviços WordPress e base de conhecimento

Reforce o seu negócio com suporte técnico profissional em áreas-chave do ecossistema WordPress.

Perguntas frequentes

Respostas práticas para aplicar o tema na execução real.

Qual é a diferença entre async e defer?#
async descarrega o script em paralelo e executa-o assim que estiver pronto, o que pode quebrar dependências. defer também descarrega em paralelo, mas só executa depois de o HTML estar totalmente processado.
O que é Critical CSS?#
É o conjunto mínimo de estilos necessário para renderizar o conteúdo acima da dobra. O resto do CSS pode carregar depois, de forma assíncrona.
Posso aplicar lazy loading a tudo?#
Não. Imagens e recursos críticos no topo da página não devem ser atrasados. O objetivo é acelerar a renderização inicial, não atrasar o conteúdo principal.

Precisa de FAQ adaptado ao setor e mercado? Criamos uma versão alinhada com os seus objetivos de negócio.

Fale connosco

Artigos Relacionados