Atributo HTML defer
O atributo HTML defer especifica que um script é executado após o término do parsing da página. Veja como usá-lo no elemento <script>.
O atributo HTML defer é um atributo boolean no elemento <script> que instrui o navegador a baixar o script em paralelo com o parsing do HTML, mas a aguardar e executá-lo somente após o parsing completo da página — imediatamente antes do evento DOMContentLoaded ser disparado.
Ele funciona apenas com scripts externos: só tem efeito quando o atributo src está presente e é ignorado em scripts inline (um <script> cujo JavaScript está entre as tags).
Por que o atributo defer existe
Um <script src="..."> simples é render-blocking. Quando o parser o encontra, interrompe a construção da página, baixa o arquivo, executa-o e só então continua. Se o script estiver no <head>, o usuário enxerga uma página em branco até o carregamento terminar.
A solução clássica era colocar as tags <script> no final do <body>, para que o HTML fosse parseado primeiro. O defer torna esse artifício desnecessário: você pode manter os scripts no <head> (favorece a legibilidade e permite que o navegador os descubra e baixe cedo), enquanto o script ainda é executado somente após o DOM estar completamente construído. Como o DOM tem a execução garantida após ser totalmente construído, scripts com defer podem consultar elementos com segurança sem precisar envolver tudo em um listener DOMContentLoaded.
defer vs async
Tanto defer quanto async permitem que o navegador baixe o script em segundo plano sem bloquear o parsing do HTML. A diferença está em quando e em que ordem os scripts são executados:
| Comportamento | defer | async |
|---|---|---|
| Bloqueia o parsing do HTML durante o download | Não | Não |
| Quando o script é executado | Após o parsing concluído, logo antes de DOMContentLoaded | Assim que termina o download (pode interromper o parsing) |
| Ordem de execução em relação a outros scripts | Preservada — executa na ordem do documento | Não garantida — o primeiro a terminar o download executa primeiro |
| DOM garantidamente pronto | Sim | Não |
Use defer quando os scripts dependem do DOM ou uns dos outros (a ordem importa). Use async para scripts independentes e autossuficientes, como analytics ou tags de anúncios, nos quais a ordem não importa e você quer que cada um execute assim que chegar.
Se nem async nem defer estiverem presentes, o script é baixado e executado imediatamente, bloqueando o parser naquele ponto.
No HTML 4.01 o comportamento do defer era dependente de implementação, enquanto o HTML5 o padronizou. Em XHTML, defer deve ser escrito como <script defer="defer"> porque a minimização de atributos é proibida.
Sintaxe
<script src="example.js" defer></script>Exemplo do atributo HTML defer
O script abaixo está no <head>, mas como é diferido, só é executado após o parágrafo existir no DOM — então document.getElementById o encontra:
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"
defer
></script>
<noscript>Sorry, your browser doesn't support JavaScript!</noscript>
</head>
<body>
<h1>Example</h1>
<p id="demo">Waiting for the deferred script...</p>
<script defer>
// This deferred external script (jQuery) is already loaded,
// and the DOM is fully parsed, so the line below works.
document.getElementById("demo").textContent =
"jQuery version " + jQuery.fn.jquery + " ran after parsing.";
</script>
</body>
</html>Nota: o
deferno<script>inline acima é ignorado — scripts inline sempre são executados no lugar. Funciona aqui somente porque é o último elemento e o script externo diferido já terminou. Para garantir que uma biblioteca externa diferida seja carregada antes do seu próprio código, mova seu código para um arquivo externo comdefertambém, pois scripts diferidos são executados na ordem do documento.