Adiar Imagens Fora da Tela no Mobile: Guia de Lazy Loading Nativo

Lazy loading nativo, content-visibility e por que o adiamento de imagens com JavaScript é peso morto

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

Adiamento de Imagens no Mobile: o padrão

Páginas mobile lutam por conexões limitadas e CPU limitada. Cada imagem fora da tela que você carrega antecipadamente rouba largura de banda das imagens e scripts que realmente importam para a renderização inicial.

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

1. Adiar imagens fora da tela no mobile: lazy loading nativo

Quando um navegador carrega uma página, ele abre um número limitado de conexões paralelas (dependendo de muitos fatores, mas 6 por domínio é uma média comum). Se essas conexões forem usadas para baixar imagens fora da tela (por exemplo, um logotipo no rodapé ou um slide de carrossel), o download de recursos críticos (tipicamente a imagem do LCP, scripts importantes e fontes) competirá por slots e largura de banda. Isso é contenção de rede, e degrada diretamente seus Core Web Vitals.

Ao adiar imagens fora da tela usando o atributo nativo loading, você prioriza o que importa. O navegador busca apenas o que é imediatamente visível, reservando largura de banda para os ativos que impactam o Largest Contentful Paint (LCP) e o First Contentful Paint (FCP). O lazy loading nativo transfere essa priorização para o próprio mecanismo do navegador, o que é mais rápido e remove a necessidade de bibliotecas de lazy loading em JavaScript.

Implementação

Para todas as imagens abaixo do viewport inicial ("the fold"), adicione o atributo loading="lazy".

<!-- Imagem Adiada Padrão -->
<img src="product-detail.jpg"
     loading="lazy"
     alt="Side view of the chassis"
     width="800"
     height="600"
     decoding="async">

Os atributos width e height são essenciais. Sem eles, o navegador não pode reservar espaço antes que a imagem carregue, o que causa Cumulative Layout Shift (CLS). 62% das páginas mobile ainda falham em definir dimensões explícitas em pelo menos uma imagem.

Como o lazy loading funciona no mobile: A Heurística do Navegador

O lazy loading nativo é superior às soluções em JavaScript porque o navegador ajusta o limite de carregamento (quando uma imagem é acionada para download) com base no Effective Connection Type (ECT).

  • Em 4G/WiFi: A engine Blink (Chrome/Edge) usa um limite conservador de cerca de 1.250px. Ela assume baixa latência e busca a imagem apenas quando o usuário rola relativamente perto.
  • Em 3G/Slow-2G: O limite se expande para cerca de 2.500px. O navegador inicia a requisição muito mais cedo para compensar os altos tempos de ida e volta, de modo que a imagem esteja pronta antes que o usuário a role para dentro da visão.

De acordo com o Web Almanac de 2025, a página mobile mediana carrega 15 imagens totalizando 911 KB. Apenas cerca de 26% dessas imagens usam loading="lazy". O restante carrega de forma ansiosa (eagerly), competindo pelas mesmas conexões limitadas. Em uma conexão mobile 4G típica, isso significa que a imagem do LCP fica presa esperando atrás de uma dúzia de imagens que o usuário não verá por vários segundos.

Exceção Crítica: A Candidata a LCP

Uma regressão de desempenho comum: aplicar loading="lazy" ao elemento Largest Contentful Paint (tipicamente a hero image). Isso atrasa a busca até que o layout esteja completo.

A pesquisa do Google mostra que fazer lazy-loading da imagem do LCP adiciona 624ms ao LCP mediano. Esse não é um risco teórico. 17% das páginas mobile ainda cometem esse erro de acordo com o Web Almanac de 2025. Se o Lighthouse sinalizar isso, veja como corrigir o aviso de LCP com lazy-load.

A imagem do LCP deve ser carregada de forma eager e priorizada:

<!-- Imagem Hero: Eager e Priorizada -->
<img src="hero.jpg"
     alt="Summer Collection"
     width="1200"
     height="800"
     loading="eager"
     fetchpriority="high">

Não combine loading="lazy" com fetchpriority="high". Eles se contradizem: lazy diz ao navegador para esperar, high diz para se apressar. O navegador ignora a dica de prioridade quando lazy está definido. Para mais informações sobre como os navegadores priorizam recursos, veja o guia de priorização de recursos.

2. Complexidades do mobile: Viewport e Touch

Os viewports no mobile não são estáticos. A área visível muda à medida que o usuário rola, rotaciona o dispositivo ou aciona o recolhimento da barra de URL. É aqui que o lazy loading nativo tem uma vantagem real sobre as soluções em JavaScript.

  • The Viewport: A área retangular visível da janela do navegador. No mobile, isso é dinâmico; muda de dimensões com base na orientação do dispositivo (retrato vs. paisagem) e no estado da interface do navegador (recolhimento das barras de URL).
  • The Fold: A borda inferior exata do viewport. É o limite que separa o conteúdo visível do conteúdo fora da tela.
  • Above the Fold: Qualquer conteúdo visível imediatamente após o carregamento da página, sem rolagem. Imagens aqui são críticas e nunca devem usar lazy-loading.
  • Below the Fold: Qualquer conteúdo localizado verticalmente após a dobra (the fold). Este conteúdo não é crítico e deve ser adiado até que o usuário role para perto dele.

O Viewport Dinâmico

Em navegadores mobile, a altura do viewport (vh) é fluida. Quando o usuário inicia uma rolagem por toque, a barra de URL e os controles de navegação frequentemente se retraem, alterando o tamanho da área visível.

Bibliotecas de lazy loading em JavaScript normalmente calculam a altura do viewport (window.innerHeight) apenas uma vez no carregamento da página. Quando navegadores mobile redimensionam dinamicamente a área visível escondendo a barra de URL durante uma rolagem, métodos em JavaScript continuam a usar o valor antigo e menor da altura. As imagens permanecem descarregadas mesmo quando entram no viewport expandido, causando placeholders em branco para os visitantes.

A engine de layout interna do navegador rastreia o viewport visual automaticamente, então os gatilhos do lazy loading nativo disparam independentemente das mudanças de tamanho do viewport. Esta é uma razão para preferir o lazy loading nativo em relação a qualquer alternativa em JavaScript.

3. Decodificação de Imagens no Mobile e Throttling de CPU

Dispositivos mobile têm CPU limitada e a decodificação de imagens neles pode ser relativamente lenta e cara. Converter um JPEG em um bitmap requer muitos ciclos de CPU. Em um processador mobile, decodificar uma sequência de imagens maiores pode bloquear a main thread de 50ms a 100ms cada, causando latência de entrada.

A Solução: content-visibility

A propriedade CSS content-visibility: auto atua como lazy rendering. Ela instrui o navegador a ignorar totalmente as fases de layout e pintura (painting) para elementos fora da tela. O elemento existe no DOM, mas não existe na Render Tree até se aproximar do viewport.

Como essa otimização funciona ignorando a renderização da subárvore de um elemento, você não pode aplicá-la diretamente a uma tag <img> (que não tem subárvore). Aplique content-visibility ao contêiner do produto ou ao card de imagem que hospeda as imagens e seu conteúdo:

@media (max-width: 768px) {
    .image-card, .product-card {
        /* Ignora a renderização do contêiner e seus filhos */
        content-visibility: auto;

        /* Essencial: Evita que o contêiner colapse para a altura de 0px */
        contain-intrinsic-size: auto 300px;
    }
}

Isso garante que mesmo se uma imagem for baixada, o navegador não pagará o custo de layout/pintura até que o usuário realmente role até ela.

O content-visibility atingiu o status Baseline em setembro de 2024 quando o Safari 18 lançou o suporte. Agora ele funciona em 93% dos navegadores globalmente. Os benchmarks do Google mostram um aumento de 7x no desempenho de renderização no carregamento inicial para páginas com muitas seções fora da tela.

Se você deseja verificar a melhoria de renderização em dispositivos reais, o Real User Monitoring mostrará o impacto real no INP e LCP em seu tráfego mobile. Em sites monitorados pelo CoreDash, as páginas que usam content-visibility: auto em grades de produtos mostram um INP cerca de 15% melhor no mobile em comparação com páginas sem isso.

4. Metodologias Legadas: Por que evitá-las

Antes que o loading="lazy" tivesse suporte nos navegadores, o JavaScript era a única opção. Com o lazy loading nativo tendo 95% de suporte global, esses métodos em JavaScript são dívida técnica. Remova-os.

A Era do Scroll Handler (2010 a 2016)

As primeiras implementações anexavam event listeners ao evento de rolagem (scroll).

// Obsoleto: não use
window.addEventListener('scroll', () => {
    images.forEach(img => {
        if (img.getBoundingClientRect().top < window.innerHeight) {
            img.src = img.dataset.src;
        }
    });
});

Bloqueio da Main Thread: O evento de rolagem dispara dezenas de vezes por segundo. Executar lógica e calcular o layout (getBoundingClientRect) durante a rolagem ativa causa quedas de frames (jank).

Layout Thrashing: Consultar propriedades geométricas força o navegador a recalcular o layout de forma síncrona, uma operação computacionalmente cara em CPUs mobile.

A Era do IntersectionObserver (2016 a 2019)

A API IntersectionObserver melhorou o desempenho ao observar mudanças na visibilidade do elemento de forma assíncrona.

// Legado: prefira loading="lazy" nativo onde for possível
const observer = new IntersectionObserver((entries) => {
    entries.forEach(entry => {
        if (entry.isIntersecting) {
            const img = entry.target;
            img.src = img.dataset.src;
            observer.unobserve(img);
        }
    });
});

Dependência de Script: Requer execução de JavaScript. Se a main thread estiver ocupada hidratando um framework (React/Vue), as imagens permanecem descarregadas, mesmo que estejam no viewport.

Falta de Consciência de Rede: Ao contrário do carregamento nativo, o IntersectionObserver usa margens fixas (por exemplo, rootMargin: '200px'). Ele não expande automaticamente seu buffer em redes lentas, levando a flashes em branco para os usuários em conexões ruins.

Para uma visão geral completa das técnicas de otimização de imagem além do lazy loading, ou para aprender sobre como adiar imagens de fundo em CSS (que o loading="lazy" não cobre), veja esses guias dedicados.

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.

Escrevo código, não relatório.

Entro no seu time por 1 ou 2 sprints. Monto o monitoramento e garanto que o time mantém as métricas no verde depois que eu saio.

Entra em contato
Adiar Imagens Fora da Tela no Mobile: Guia de Lazy Loading NativoCore Web Vitals Adiar Imagens Fora da Tela no Mobile: Guia de Lazy Loading Nativo