JavaScript no Head vs Footer: Como Isso Afeta os Core Web Vitals

Por que o defer no head é a melhor prática moderna, e quando colocá-lo no footer ainda faz sentido

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

A resposta curta: defer no head

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

A recomendação clássica era colocar o JavaScript no rodapé (footer). Esse conselho está desatualizado. Com o suporte a async e defer em todos os navegadores, o melhor lugar para a maioria dos scripts é no <head> com um atributo defer.

O motivo se resume ao preload scanner (analisador de pré-carregamento): o seu navegador descobre os scripts no head imediatamente e começa a baixá-los em paralelo com a análise (parsing) do HTML. Os scripts no footer são descobertos mais tarde, o que significa um início de download mais tardio. O resultado é o mesmo comportamento não bloqueante (non-blocking), mas com uma descoberta de recursos mais rápida.

De acordo com o Web Almanac de 2025, 85% das páginas ainda falham na auditoria de recursos de bloqueio de renderização (render-blocking). Este é um número enorme. Enquanto isso, o Total Blocking Time (Tempo Total de Bloqueio) em dispositivos móveis aumentou 58% ano a ano, atingindo uma mediana de 1.916 ms. O JavaScript está ficando mais pesado, não mais leve. Acertar a localização do seu script é uma das coisas mais fáceis que você pode fazer para melhorar o seu First Contentful Paint e o Largest Contentful Paint.

Como o preload scanner funciona

O preload scanner é um segundo analisador HTML que funciona à frente do analisador principal. Ele examina rapidamente o HTML bruto e começa a buscar recursos críticos (imagens, CSS, JavaScript) antes que o analisador principal chegue até eles. O preload scanner busca os recursos mais ou menos na ordem em que os descobre.

É aqui que o local do script importa. Um script no <head> é descoberto quase imediatamente. Um script no final do <body> é descoberto mais tarde, especialmente em documentos HTML grandes. Esse atraso pode lhe custar centenas de milissegundos em uma conexão móvel.

Scripts injetados dinamicamente (criados via JavaScript) são totalmente invisíveis para o preload scanner. O scanner descobre apenas os recursos que existem na marcação (markup) HTML retornada pelo servidor. É por isso que adiar (defer) o JavaScript por meio de atributos HTML é quase sempre melhor do que injetar scripts com código.

JavaScript no head

Colocar o JavaScript no <head> da página proporciona a descoberta mais precoce possível pelo preload scanner.

Vantagens

  1. Descoberta antecipada: O preload scanner encontra os scripts do head antes de qualquer conteúdo do body. O download começa o mais cedo possível.
  2. Execução mais cedo: Scripts no head (com defer) executam antes dos scripts descobertos mais tarde no documento. Para uma comparação detalhada, veja JavaScript defer vs async e os Core Web Vitals.
  3. Separação de código: Manter as referências de script no <head> as separa da marcação de conteúdo, tornando o HTML mais fácil de manter.

Desvantagens

  1. Bloqueio de renderização (sem defer ou async): Um <script> simples no head bloqueia a análise do HTML até que o script seja baixado e executado. Isso acaba com o seu First Contentful Paint. Sempre use defer ou async em scripts externos no head para evitar isso.
  2. Competição por largura de banda: Scripts do head de alta prioridade competem por largura de banda (bandwidth) com seu CSS, fontes e imagem LCP. Em conexões mais lentas, isso pode empurrar seu Largest Contentful Paint para além do limite de 2,5 segundos.

Quando usar a colocação no head

Use o <head> para scripts que são críticos para a experiência da página: seu menu, aviso de cookies, slider ou qualquer script que afete o que o visitante vê acima da dobra (above the fold). Adicione defer (ou async se a ordem de execução não importar) para evitar o bloqueio de renderização. Bibliotecas de detecção de recursos (feature detection) também pertencem ao head, já que precisam ser executadas antes que o body seja analisado.

JavaScript no footer

Colocar o JavaScript logo antes da tag de fechamento </body> foi o conselho de performance padrão por anos. A ideia: deixar o HTML renderizar primeiro, baixar os scripts depois.

Vantagens

  1. Não bloqueante por padrão: Scripts de footer não bloqueiam a renderização inicial porque o HTML acima deles já foi analisado.
  2. Menor competição por largura de banda: No momento em que o navegador chega aos scripts do footer, seu CSS, fontes e imagem LCP já começaram a ser baixados.

Desvantagens

  1. Descoberta tardia: O preload scanner encontra scripts no footer mais tarde do que scripts no head. Em uma página grande, isso significa um início de download e uma execução mais tardios.
  2. Padrão obsoleto: <script defer> no <head> atinge o mesmo comportamento não bloqueante com descoberta mais cedo. A colocação no footer era a solução alternativa (workaround) antes do defer ter suporte universal nos navegadores. Essa era acabou.

Quando a colocação no footer ainda faz sentido

A colocação no footer pode fazer sentido para scripts que você realmente não quer que compitam por largura de banda durante o carregamento inicial da página: analytics, ferramentas de teste A/B ou widgets sociais. Mas mesmo para estes, o defer no head costuma ser a melhor escolha devido à descoberta mais precoce pelo preload scanner.

Atributos de script modernos

Além do async e do defer, existem mais dois atributos que valem a pena conhecer:

type="module": Scripts de módulo (module) são adiados (deferred) por padrão. Você não precisa adicionar defer a um script module porque ele já se comporta dessa maneira. Adicionar async a um script module substitui o comportamento padrão de adiamento e faz com que ele seja executado assim que terminar de baixar.

fetchpriority: Por padrão, scripts async e defer recebem prioridade de rede Baixa (Low). Adicionar fetchpriority="high" a um script async lhe dá um download não bloqueante com prioridade Alta (High). Essa é a combinação ideal para scripts que são cruciais para a user experience, mas que não devem bloquear a renderização. Para o cenário completo, veja o guia para priorização de recursos e os níveis de prioridade do JavaScript.

Uma estratégia prática para a localização de scripts

Nem todos os scripts merecem o mesmo tratamento. Eu uso uma abordagem de quatro níveis:

  1. Scripts críticos para a renderização: Scripts que afetam o layout visível da página (menu, slider, interface acima da dobra). Coloque no <head> sem o defer se eles precisarem ser executados antes do primeiro paint. Mantenha-os o menor possível, porque eles bloqueiam a renderização e prejudicarão os seus Core Web Vitals.
  2. Scripts importantes: Scripts cruciais para conversão ou interação (formulários, navegação, consentimento de cookies). Coloque no <head> com defer ou async.
  3. Scripts normais: Scripts que não afetam a primeira renderização da página (carrosséis, modais, abas). Coloque no <head> com defer.
  4. Scripts bons de se ter (nice-to-have): Scripts dos quais você poderia abrir mão se fosse absolutamente necessário (analytics, widgets de chat, compartilhamento social). Carregue-os depois que a página terminar de renderizar, usando o evento load ou requestIdleCallback. Veja 16 métodos para adiar o JavaScript em busca de técnicas. Se você possui muito JavaScript não utilizado nessa categoria, veja como reduzir o JavaScript não utilizado.

Os eventos DOMContentLoaded e load permitem que você controle o momento de execução (timing), independentemente de onde o script está localizado no HTML. Isso é útil para garantir que seu código seja executado no momento certo.

Exemplos de código

Exemplo 1: JavaScript no head (bloqueio de renderização)

<!DOCTYPE html>
<html>
<head>
    <title>Exemplo de JavaScript no Head</title>
    <script>
        function showMessage() {
            alert("Olá do JavaScript no head!");
        }
    </script>
    <!-- Este script bloqueia a renderização -->
    <script src="script.js"></script>
</head>
<body>
    <button onclick="showMessage()">Clique Aqui</button>
</body>
</html>

Neste exemplo, o script.js no <head> bloqueia a renderização. O navegador não exibirá o botão até que o script tenha sido baixado e executado. Adicione o defer à tag script para consertar isso.

Exemplo 2: JavaScript no footer

<!DOCTYPE html>
<html>
<head>
    <title>Exemplo de JavaScript no Footer</title>
</head>
<body>
    <button onclick="showMessage()">Clique Aqui</button>
    <!-- Script no final do body -->
    <script src="script.js"></script>
    <script>
        function showMessage() {
            alert("Olá do JavaScript no footer!");
        }
    </script>
</body>
</html>

Aqui, o script.js carrega depois do conteúdo HTML, então ele não bloqueia a renderização. Mas o preload scanner o descobre mais tarde do que descobriria no head. Usar <script defer src="script.js"></script> no <head> oferece o mesmo comportamento não bloqueante com uma descoberta de download antecipada.

Exemplo 3: Usando event listeners

<!DOCTYPE html>
<html>
<head>
    <title>Exemplo de Event Listener</title>
    <script>
        window.addEventListener('load', function() {
            console.log("A página está totalmente carregada.");
        });
    </script>
</head>
<body>
    <!-- Conteúdo da página -->
</body>
</html>

O event listener de load assegura que o código dentro do callback seja executado somente depois que a página estiver totalmente carregada, não importando onde o script seja colocado. Isso é proveitoso para inicializações que não são críticas e que devam aguardar até que tudo o mais esteja preparado.

Verifique as suas mudanças

Depois de migrar os scripts do footer (rodapé) para o defer no <head>, certifique-se do impacto usando Real User Monitoring. O seu FCP e o LCP devem melhorar os dois em uníssono. Englobando os sites monitorados pela CoreDash, as origens (origins) que adotam o defer em grande parte dos seus scripts revelam uma mediana correspondente a um FCP com velocidade 18% maior no que diz respeito as origens dependentes e baseadas na alocação no rodapé.

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.

The RUM tool I built for my own clients.

CoreDash is what I use to audit enterprise platforms. Under 1KB tracking script, EU hosted, no consent banner. AI with MCP support built in. The same tool, available to everyone.

Create Free Account
JavaScript no Head vs Footer: Como Isso Afeta os Core Web VitalsCore Web Vitals JavaScript no Head vs Footer: Como Isso Afeta os Core Web Vitals