Programação Por Equipe DevBras

Capa do artigo: Página que pula quando a imagem carrega: width, height e o arquivo do tamanho certo

Página que pula quando a imagem carrega: width, height e o arquivo do tamanho certo

Reserve o espaço de cada imagem com width e height ou aspect-ratio, sirva arquivos perto do tamanho exibido e use lazy loading só onde ajuda.

A pessoa vai tocar em "Ver detalhes" no celular, a foto do produto termina de carregar acima do botão, empurra tudo 280 pixels para baixo e o dedo acerta o anúncio. Ela não volta. A resposta curta: declare width e height em toda img, com as dimensões reais do arquivo, e use max-width: 100%; height: auto no CSS. O navegador calcula a proporção antes de baixar a imagem e reserva o retângulo certo. Depois, sirva um arquivo perto do tamanho mostrado e não aplique carregamento preguiçoso na imagem principal do topo.

Esse pulo tem nome nas métricas do Google: CLS, Cumulative Layout Shift. Para ser considerado bom, ele deve ficar em 0,1 ou menos. Imagem sem dimensão é uma das causas mais comuns de passar disso.

Por que o texto desce quando a foto chega

O navegador monta a página à medida que o HTML chega. Quando encontra uma img sem tamanho, ele não sabe quanto espaço ela vai ocupar, então reserva zero de altura e continua desenhando o texto logo abaixo. Quando os primeiros bytes da imagem chegam, ele descobre as dimensões, abre o espaço e empurra o resto da página. Em rede rápida isso dura um instante. Em 4G fraco, dura o suficiente para a pessoa já ter começado a ler ou a tocar.

Os navegadores atuais usam os atributos width e height para calcular a proporção da imagem antes de ela chegar. Com height: auto no CSS, a imagem continua responsiva: a largura acompanha o contêiner e a altura reservada segue a proporção declarada. Por isso os atributos voltaram a ser recomendados, mesmo em layouts fluidos.

O segundo problema é o peso. No nosso exemplo, a loja mostra cards de 400 pixels de largura com fotos de 4000 por 3000 pixels, 2,8 MB cada. Doze cards na listagem somam mais de 30 MB. A página fica lenta, o pulo dura mais e o plano de dados da pessoa paga a conta.

Como reservar o espaço e servir o tamanho certo

  1. Coloque width e height em todas as imagens, com as dimensões do arquivo ou qualquer par com a mesma proporção.
  2. Garanta a regra de CSS responsiva para que os atributos não fixem o tamanho em pixels na tela.
  3. Para imagens com recorte, defina aspect-ratio no contêiner e use object-fit: cover na imagem.
  4. Gere versões redimensionadas do arquivo original, perto da largura exibida e do dobro dela para telas de alta densidade.
  5. Use srcset e sizes para o navegador escolher a versão adequada.
  6. Aplique loading="lazy" nas imagens abaixo da primeira dobra, e nunca na imagem principal do topo.
  7. Meça com rede lenta simulada e confira se ainda há deslocamento.

O HTML e o CSS do card

<article class="card">
  <img
    src="/img/tenis-azul-800.webp"
    srcset="/img/tenis-azul-400.webp 400w, /img/tenis-azul-800.webp 800w"
    sizes="(max-width: 600px) 100vw, 400px"
    width="800" height="600"
    alt="Tênis de corrida azul com sola branca, vista lateral"
    loading="lazy" decoding="async">
  <h2>Tênis Corrida Leve</h2>
  <p>R$ 299,90</p>
</article>
img {
  max-width: 100%;
  height: auto;
}

Os atributos width="800" height="600" dizem a proporção 4:3. Com a regra de CSS, o card de 400 pixels reserva 300 de altura antes do primeiro byte. O srcset lista duas versões com a largura real de cada uma, e o sizes diz ao navegador quanto da tela a imagem ocupa: a largura toda em telas até 600 pixels, 400 pixels nas maiores. Com isso, um celular com densidade 2 e tela de 390 pixels escolhe a versão de 800; um monitor comum escolhe a de 400. O texto alternativo segue o que está em texto alternativo descreve a imagem.

Imagem com recorte fixo

Quando o design pede que todas as fotos da grade tenham a mesma proporção, mesmo que os arquivos variem, reserve o espaço no CSS:

.card img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
}

A propriedade aspect-ratio garante o retângulo, e object-fit: cover recorta a imagem para preencher sem distorcer.

Como gerar as versões menores

Com ImageMagick 7, o comando magick redimensiona mantendo a proporção quando você informa só a largura:

magick tenis-azul.jpg -resize 800x -quality 80 tenis-azul-800.webp
magick tenis-azul.jpg -resize 400x -quality 80 tenis-azul-400.webp

No exemplo, a versão de 800 pixels ficou com cerca de 70 KB contra os 2,8 MB do original. O número exato depende da foto, mas a ordem de grandeza costuma ser essa. Se o upload vem do usuário, gere essas versões no servidor no momento do envio, como mostrado em redimensionar imagem no servidor.

Onde o lazy loading ajuda e onde atrapalha

O atributo loading="lazy" faz o navegador adiar o download de imagens fora da tela até que a pessoa role perto delas. Na listagem de doze cards, as oito de baixo não precisam chegar antes do texto. Isso economiza banda e libera a rede para o que importa primeiro.

Na imagem principal do topo, por exemplo a foto grande da página de produto, o efeito é o contrário: ela só começa a baixar depois que o navegador calcula o layout e confirma que está visível. Essa imagem costuma ser o maior elemento da tela, medido pela métrica LCP. Deixe-a com carregamento normal e, se quiser priorizar, use fetchpriority="high". O post site mais rápido: por onde começar coloca essa escolha no contexto das outras otimizações.

Como ver o pulo acontecer

No Chrome, abra as ferramentas de desenvolvedor, limite a rede a uma conexão lenta na aba Network e recarregue. Na gaveta Rendering, ative a opção que destaca regiões de deslocamento de layout: cada pulo pisca em azul. O Lighthouse e o painel Performance mostram o valor de CLS e apontam os elementos que mais se moveram. Para dados de visitantes reais, o relatório de Core Web Vitals do Search Console agrupa as páginas por situação.

Erros comuns

  • Imagem sem width e height. O navegador reserva zero de altura e empurra o conteúdo quando ela chega.
  • Atributos com proporção diferente do arquivo. O espaço reservado não bate com a imagem e o pulo acontece mesmo assim, ou a imagem aparece distorcida.
  • Atributos sem height: auto no CSS. A imagem fica presa ao tamanho em pixels e transborda em telas estreitas.
  • Arquivo de 4000 pixels num card de 400. A página pesa dezenas de megabytes e demora mais para estabilizar.
  • Lazy loading na imagem principal do topo. O maior elemento da tela chega por último e a página parece mais lenta.
  • Testar só no Wi-Fi do escritório. O pulo dura milissegundos ali e passa despercebido; no celular da pessoa, dura segundos.

Checklist

  • Toda img tem width e height com a proporção real do arquivo.
  • O CSS global tem max-width: 100% e height: auto para imagens.
  • Grades com recorte usam aspect-ratio e object-fit.
  • Cada imagem tem versões próximas da largura exibida e do dobro dela.
  • srcset e sizes estão declarados nas imagens de conteúdo.
  • A imagem principal do topo não usa loading="lazy".
  • O CLS medido no Lighthouse fica em 0,1 ou menos com rede lenta.

Abra a sua página de produto com a rede limitada e as regiões de deslocamento destacadas: quantas vezes a tela pisca em azul antes de parar quieta?

Avalie este artigo

Referência: https://web.dev/articles/optimize-cls