Lazy loading é a prática de adiar o carregamento de recursos que não são necessários imediatamente. Em vez de baixar todas as imagens e iframes quando a página carrega, apenas os que estão na viewport (visíveis na tela) são carregados inicialmente. Os demais carregam conforme o usuário rola a página.
Por que usar lazy loading
Uma página de e-commerce com 40 imagens de produtos pode ter 15-20MB de imagens. Sem lazy loading, o browser tenta baixar todas ao mesmo tempo, mesmo que o usuário veja apenas 6 imagens sem rolar.
Com lazy loading: apenas as 6 imagens visíveis carregam inicialmente. O restante carrega conforme o usuário navega. Resultado: tempo de carregamento inicial até 5x menor.
Lazy loading nativo (recomendado)
Desde 2019, os principais browsers suportam lazy loading nativo com o atributo loading:
<img src="produto.webp" loading="lazy" alt="Produto" width="400" height="300">
Suporte atual: Chrome, Firefox, Edge, Safari 15.4+. Cobre mais de 95% dos usuários.
Para iframes (vídeos do YouTube, Google Maps, etc.):
<iframe src="https://www.youtube.com/embed/..." loading="lazy" title="Vídeo"></iframe>
A regra mais importante: nunca use lazy na imagem LCP
O maior erro com lazy loading é aplicá-lo indiscriminadamente em todas as imagens, incluindo o hero.
A imagem LCP (maior elemento visible da página) precisa carregar o mais rápido possível. Com loading="lazy", o browser adia o carregamento dela, piorando significativamente o LCP.
Regra prática:
- Imagens above-the-fold (visíveis sem rolar): sem
loading="lazy", e na imagem principal adicionefetchpriority="high" - Imagens below-the-fold: use
loading="lazy"
<!-- Hero - imagem principal da página -->
<img src="hero.webp" fetchpriority="high" alt="Hero" width="1200" height="600">
<!-- Galeria de produtos - abaixo do fold -->
<img src="produto1.webp" loading="lazy" alt="Produto 1" width="400" height="400">
<img src="produto2.webp" loading="lazy" alt="Produto 2" width="400" height="400">
Definir dimensões: obrigatório com lazy loading
Sem width e height, o browser não sabe o tamanho da imagem antes de baixá-la. Isso causa CLS (Cumulative Layout Shift) quando a imagem carrega - o layout pula.
<!-- CORRETO: dimensões definidas -->
<img src="produto.webp" loading="lazy" width="400" height="300" alt="Produto">
<!-- ERRADO: sem dimensões - vai causar CLS -->
<img src="produto.webp" loading="lazy" alt="Produto">
Lazy loading de iframes pesados
Iframes são frequentemente ignorados no lazy loading, mas são dos elementos mais pesados de uma página:
- YouTube embed: sem lazy loading, carrega scripts e assets do YouTube mesmo fora da tela
- Google Maps: carrega toda a API de mapas imediatamente
- Widgets de redes sociais: scripts pesados de terceiros
<!-- YouTube com lazy loading -->
<iframe
src="https://www.youtube.com/embed/VIDEO_ID"
loading="lazy"
width="560"
height="315"
title="Título do vídeo"
frameborder="0"
allowfullscreen
></iframe>
Técnica avançada para YouTube: use uma thumbnail como preview e carregue o iframe só ao clicar:
<div class="youtube-facade" data-videoid="VIDEO_ID" style="width:560px;height:315px;background:url(thumbnail.jpg)">
<button onclick="this.parentElement.innerHTML='<iframe src=...>'">▶ Assistir</button>
</div>
Lazy loading de componentes JavaScript
Para aplicações com JavaScript, componentes não visíveis inicialmente podem ser carregados sob demanda:
Com import() dinâmico:
// Carrega o componente só quando o usuário clica em "ver mais"
document.getElementById('ver-mais').addEventListener('click', async () => {
const { renderGaleria } = await import('./galeria.js');
renderGaleria();
});
Com Intersection Observer (carrega quando entra na viewport):
const observer = new IntersectionObserver((entries) => {
entries.forEach(async (entry) => {
if (entry.isIntersecting) {
const { inicializar } = await import('./componente-pesado.js');
inicializar(entry.target);
observer.unobserve(entry.target);
}
});
});
document.querySelectorAll('.componente-lazy').forEach(el => observer.observe(el));
Seu site carrega recursos desnecessários no início?
Auditamos e implementamos lazy loading correto no seu site - sem prejudicar LCP, sem CLS, com impacto real no tempo de carregamento.
Otimizar carregamento do meu siteFAQ
O lazy loading nativo é suficiente ou preciso de biblioteca JavaScript?
Para imagens e iframes, o loading="lazy" nativo é suficiente para a maioria dos casos e tem a vantagem de não adicionar nenhum JavaScript à página. Bibliotecas como lazysizes ainda fazem sentido para suporte a browsers mais antigos ou lazy loading de imagens de fundo CSS.
Como implementar lazy loading em imagens de fundo CSS?
O loading="lazy" funciona apenas em tags <img> e <iframe>. Para backgrounds CSS, use Intersection Observer para adicionar/remover uma classe que aplica o background:
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('loaded');
}
});
});
.section-bg { background: none; }
.section-bg.loaded { background-image: url('fundo.webp'); }
Lazy loading afeta SEO e indexação do Google?
O Googlebot renderiza JavaScript e suporta lazy loading. Contudo, imagens abaixo do fold podem demorar mais para serem indexadas. Para SEO, o mais importante é garantir que as imagens principais (above-the-fold, imagem de produto em destaque) não usem lazy loading.
Qual a “distância” que o browser usa para pré-carregar imagens lazy?
O browser começa a carregar imagens lazy quando elas estão dentro de uma margem configurada internamente (geralmente 1250px a 2500px abaixo da viewport, dependendo da velocidade de conexão detectada). Isso garante que as imagens carreguem antes do usuário rolar até elas.