Como remover CSS e JS que bloqueiam renderização

Como remover CSS e JS que bloqueiam renderização

Última verificação: 22 de setembro de 2026
8 min de leitura
Guia
Core Web Vitals

Quando o navegador carrega a tua 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), tens de corrigir isto.

#1. Javascript: Async e defer

A velha guarda dizIA: “mete scripts no rodapé (wp_footer)”. A nova guarda diz: “usa 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”. Ativa-a.

Isto normalmente resolve 90% dos problemas de JS.

#2. CSS: Critical CSS

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

A solução é Critical CSS.

  1. Pega apenas no CSS necessário para mostrar conteúdo “acima da dobra” (visível sem scroll).
  2. Cola-o inline em <style> no header.
  3. Carrega 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).
  2. CSS: Critical CSS inline + resto assíncrono.
  3. Fontes: Usa font-display: swap.

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

#Diagnóstico: descobrir o que bloqueia mesmo

O relatório do Lighthouse lista os ficheiros bloqueadores, mas não diz que parte deles é realmente usada. Abre as DevTools, corre “Show Coverage” a partir da paleta de comandos e recarrega. A coluna “Unused Bytes” separa dois problemas muito diferentes: CSS a mais, ou CSS carregado no momento errado. Num tema com construtor de páginas, a fatia não utilizada na página inicial costuma andar entre 70 e 90 por cento, e nesse caso minificar não resolve nada de relevante.

Depois vai ao separador Network e procura 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.

#Que atributo usar em cada caso

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.

#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: o WordPress recusa adiar o script enquanto o próprio jQuery não estiver adiado. O erro clássico deixa de ser possível.

Para instalações mais antigas, ou para um plugin que não podes 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;
}

Repara 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í tens um defeito que não escreveste.

#O pedido mais rápido é o que não acontece

Antes de adiar, pergunta 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.

#Critical CSS sem a página a piscar

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.

Há três coisas que decidem o resultado. O tamanho: mantém o bloco embutido abaixo de cerca de 15 KB, porque acima disso passas a pagar uma resposta HTML maior em cada visita e apenas mudaste 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 gera para as duas larguras e junta o resultado. E o teste em ligação lenta: põe as DevTools em “Slow 3G” e recarrega. Se vires texto sem estilos durante meio segundo antes de o layout encaixar, falta conteúdo no bloco crítico.

#Tipos de letra, o bloqueio esquecido

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. Junta um preload, com crossorigin, que é exigido para fontes mesmo quando o ficheiro está no teu 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.

#Scripts de terceiros costumam ser o tecto

Podes optimizar o teu 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. Carrega 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 usa 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.

#Medir antes e depois

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. Regista 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.

#Cinco erros que custam mais caro

  • 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 cerca de 15 KB, cada visita paga a conta.
  • 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 teu.
  • 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.

FAQ do artigo

Perguntas frequentes

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

SEO-readyGEO-readyAEO-ready3 Q&A
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