Adiar imagens fora da tela em dispositivos móveis

Adiar imagens fora da tela em dispositivos móveis

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

Adiamento de Imagens em Dispositivos Móveis: o padrão

O desempenho móvel é frequentemente limitado pela latência de rede (RTT) e pela disponibilidade de CPU da thread principal. Adiar imagens fora da tela em dispositivos móveis resolve ambos os problemas, prevenindo a contenção de largura de banda no caminho crítico de renderização e distribuindo os custos de decodificação de imagens ao longo da duração da sessão.

Este documento explica como adiar imagens de forma eficaz em dispositivos móveis, quando utilizá-lo e aborda as restrições mecânicas específicas dos viewports móveis.

priority waterfall web dev example

1. Adiar imagens fora da tela em dispositivos móveis: 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 slide de carrossel), o download de recursos críticos (tipicamente a imagem LCP, scripts importantes e fontes competirão por slots e largura de banda). Este fenómeno, conhecido como Contenção de Rede, degrada diretamente os Core Web Vitals.

Ao adiar imagens fora da tela usando o atributo nativo loading, podemos priorizar recursos importantes e otimizar o Caminho Crítico de Renderização. O navegador busca apenas o que é imediatamente visível, reservando largura de banda para os recursos que impactam estritamente o First Contentful Paint (FCP) e o Largest Contentful Paint (LCP). O método de lazy loading nativo transfere essa lógica de priorização para o mecanismo interno muito mais rápido do navegador, eliminando a necessidade de bibliotecas JavaScript antigas e lentas.

Implementação

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

<!-- Standard Deferred Image -->
<img src="product-detail.jpg"
     
     alt="Side view of the chassis"
     width="800"
     height="600"
     decoding="async">

Como o lazy loading funciona em dispositivos móveis: A Heurística do Navegador

O lazy loading nativo é superior às soluções JavaScript porque o navegador ajusta o limiar de carregamento (quando uma imagem é acionada para download) com base no Tipo de Conexão Efetiva (ECT).

  • Em 4G/WiFi: O motor Blink (Chrome/Edge) emprega um limiar conservador (por exemplo, 1250px). Ele assume baixa latência e busca a imagem apenas quando o utilizador está relativamente próximo do viewport.
  • Em 3G/Slow-2G: O limiar expande (por exemplo, 2500px). O navegador inicia o pedido muito mais cedo em relação à posição de scroll para compensar os altos tempos de ida e volta, garantindo que a imagem esteja pronta antes do utilizador a rolar para a área visível.

Exceção Crítica: O Candidato a LCP

Uma regressão de desempenho comum ocorre quando os programadores aplicam loading="lazy" ao elemento Largest Contentful Paint (LCP) (tipicamente a imagem hero). Isto atrasa a busca até que o layout esteja completo.

Estratégia Correta para o LCP: A imagem LCP deve ser carregada de forma eager e priorizada.

<!-- Hero Image: Eager and Prioritized -->
<img src="hero.jpg"
     alt="Summer Collection"
     width="1200"
     height="800"
     
     > 

2. Complexidades móveis: Viewport e Toque

Os viewports móveis introduzem desafios de renderização específicos que a implementação nativa lida de forma mais robusta do que soluções baseadas em scripts.

  • O Viewport: A área retangular visível da janela do navegador. Em dispositivos móveis, esta é dinâmica; muda de dimensões com base na orientação do dispositivo (retrato vs. paisagem) e no estado do chrome do navegador (barras de URL retraídas).
  • The Fold: A borda inferior exata do viewport. É o limiar que separa o conteúdo visível do conteúdo fora da tela.
  • Above the Fold: Qualquer conteúdo visível imediatamente ao carregar a página sem necessidade de scroll. As imagens aqui são frequentemente críticas e quase nunca devem ter lazy loading.
  • Below the Fold: Qualquer conteúdo localizado verticalmente abaixo do fold. Este conteúdo é Não Crítico e deve ser adiado até que o utilizador role para perto dele.

above and below the mobile fold 22 01 26

O Viewport Dinâmico

Nos navegadores móveis, a altura do viewport (vh) é fluida. Quando o utilizador inicia um scroll por toque, a barra de URL e os controlos de navegação frequentemente retraem, alterando o tamanho da área visível.

As bibliotecas JavaScript de adiamento de imagens geralmente calculam a altura do viewport (window.innerHeight) apenas uma vez no início do carregamento da página.  Quando os navegadores móveis redimensionam dinamicamente a área visível ao ocultar a barra de URL durante o scroll, os métodos JavaScript continuam a usar o valor de altura antigo e menor. Isto fazia com que as imagens permanecessem descarregadas mesmo quando entravam fisicamente na área expandida do viewport, causando uma má UX para os visitantes.

O Tratamento Nativo resolve este problema uma vez que o motor de layout interno do navegador rastreia o viewport visual automaticamente, garantindo que os acionadores disparam independentemente de quaisquer alterações no tamanho do viewport.

3. Decodificação de Imagens em Dispositivos Móveis e Limitação de CPU

Os dispositivos móveis têm CPU limitada e a decodificação de imagens em dispositivos móveis pode ser relativamente lenta e cara. Converter um JPEG num bitmap requer muitos ciclos de CPU. Num processador móvel, decodificar uma sequência de imagens maiores pode bloquear a thread principal por 50ms–100ms cada, causando latência de entrada.

A Solução: content-visibility

Para resolver isto, podemos usar a propriedade e valor CSS content-visibility: auto. Esta propriedade atua como um padrão para "Renderização Lazy." Ela instrui o navegador a ignorar as fases de layout e pintura para elementos fora da tela por completo. O elemento existe no DOM, mas não existe na Render Tree até se aproximar do viewport.

Como esta otimização funciona ao ignorar a renderização da subárvore de um elemento, não é possível aplicá-la diretamente a uma tag <img> (que não possui subárvore). Deve-se aplicar content-visibility ao contentor do produto ou cartão de imagem que hospeda essas imagens e o seu conteúdo

@media (max-width: 768px) {
    .image-card, .product-card {
        /* Skip rendering of the container and its children */
        content-visibility: auto;
        
        /* Essential: Prevents container from collapsing to 0px height */
        contain-intrinsic-size: auto 300px;
    }
}

Isto garante que, mesmo que uma imagem seja descarregada, o navegador não paga o custo de layout/pintura até que o utilizador realmente role até ela.

4. Metodologias Legacy: Por que evitá-las

Antes do suporte nativo, os programadores dependiam de JavaScript para o adiamento de imagens em dispositivos móveis. Estes métodos ainda são amplamente utilizados, mas devem ser considerados como dívida técnica!

A Era do "Scroll Handler" (2010–2016)

As primeiras implementações anexavam event listeners ao evento scroll.

// OBSOLETE: Do not use
window.addEventListener('scroll', () => {
    images.forEach(img => {
        if (img.getBoundingClientRect().top < window.innerHeight) {
            img.src = img.dataset.src;
        }
    });
});

Bloqueio da Thread Principal: O evento scroll dispara dezenas de vezes por segundo. Executar lógica e calcular layout (getBoundingClientRect) durante o scroll ativo causava quedas de frames (jank).

Layout Thrashing: Consultar propriedades geométricas força o navegador a recalcular sincronamente o estilo de layout, uma operação computacionalmente cara em CPUs móveis. 

A Era do IntersectionObserver (2016–2019)

A API IntersectionObserver melhorou o desempenho ao observar assincronamente as alterações na visibilidade dos elementos. 

// DEPRECATED: Use native loading where possible
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 thread principal estiver ocupada a hidratar um framework (React/Vue), as imagens permanecem descarregadas mesmo que estejam no viewport.

Falta de Consciência de Rede: Ao contrário do loading nativo, o IntersectionObserver utiliza margens fixas (por exemplo, rootMargin: '200px'). Não expande automaticamente o seu buffer em redes lentas, levando a "flashes brancos" para utilizadores com conexões fracas.


Pinpoint the route, device, and connection that fails.

CoreDash segments every metric by route, device class, browser, and connection type. Real time data. Not the 28 day average Google gives you.

Explore Segmentation
Adiar imagens fora da tela em dispositivos móveisCore Web Vitals Adiar imagens fora da tela em dispositivos móveis