CategoriaCódigo e arquitetura
Imagens no site: tamanho, formato e a hora de carregar
Imagem leve depende de quatro decisões no HTML. Entregar um arquivo do tamanho em que ele aparece, com srcset e sizes. Usar um formato moderno, como WebP ou AVIF. Declarar largura e altura para o navegador reservar o espaço. E escolher a hora de carregar: loading="lazy" só para o que fica abaixo da dobra, prioridade alta para a imagem principal do topo (web.dev, carregamento lento no navegador). A última é a que mais engana, porque um atributo no lugar errado atrasa justamente a imagem que a pessoa vê primeiro.
Por que a imagem pesa tanto
Segundo o HTTP Archive, citado pelo artigo do web.dev sobre carregamento lento, a imagem é o recurso mais pedido na maioria dos sites e o que mais gasta banda. Entre os 10% de sites mais pesados nesse quesito, cada um manda mais de 5 MB de imagens, tanto no computador quanto no celular.
O peso não é o único problema. A imagem grande do topo muitas vezes é o elemento medido pela Maior exibição de conteúdo, o LCP, métrica que marca quando o principal da página apareceu. Uma imagem atrasada ali atrasa a métrica inteira.
Qual imagem merece peso e onde ela fica
Antes de otimizar, vale perguntar se a imagem precisa existir. Nos estudos de rastreamento ocular do NN/g, as pessoas examinam fotos que carregam informação, como produto e gente de verdade, e ignoram as que só enfeitam a página (Jakob Nielsen, NN/g (em inglês)). Imagem decorativa custa bytes e não devolve atenção.
Depois vem a posição. Num estudo de 2018 do NN/g, as pessoas passaram cerca de 57% do tempo de leitura na primeira tela e 74% nas duas primeiras (Therese Fessenden, NN/g (em inglês)). É por isso que a imagem do topo merece prioridade e o resto pode esperar a rolagem.
A dificuldade é que a primeira tela muda de aparelho para aparelho. Um layout responsivo tem duas, três ou mais dobras, uma para cada tamanho de tela (Amy Schade, NN/g (em inglês)). Quem marca as imagens no HTML precisa decidir sem saber em qual tela a página vai abrir.
Um arquivo para cada largura de tela
O guia de imagens responsivas do MDN separa dois problemas. O primeiro é a troca de resolução: a mesma foto, em arquivos de larguras diferentes. O segundo é a direção de arte: outro recorte da foto para outra tela.
Para a troca de resolução bastam dois atributos na tag <img>:
srcsetlista os arquivos disponíveis e a largura real de cada um, comofoto-480.jpg 480w.sizesdiz quanto espaço a imagem vai ocupar na tela em cada condição, como(max-width: 480px) 440px.
Com isso o navegador escolhe o menor arquivo que ainda preenche o espaço com nitidez. No exemplo do MDN, a versão de 800 pixels pesa 128 KB e a de 480 pixels pesa 63 KB (MDN). Numa página com dezenas de fotos, essa diferença se soma.
O mesmo guia explica por que isso fica no HTML, e não num script. O navegador começa a baixar as imagens antes de ler o CSS e o JavaScript da página. Quando um script descobrisse a largura da tela, o arquivo grande já estaria a caminho (MDN).
Para direção de arte, o caminho é o elemento <picture>, com uma <source> por recorte e uma <img> no fim como reserva.
Formato moderno, com plano B
WebP e AVIF guardam a mesma foto em menos bytes que JPEG e PNG. O <picture> permite oferecer o formato novo e manter o antigo para quem não o aceita. Cada <source> declara o tipo no atributo type, e o navegador pula o que não sabe ler (MDN).
Quem usa Astro não precisa montar isso à mão. O componente <Picture /> gera AVIF e WebP a partir de um PNG e deixa o original como reserva. Já o <Image /> converte para WebP por padrão. Isso vale só para imagens guardadas em src/; o que fica em public/ sai como está (documentação do Astro sobre imagens (em inglês)).
Reservar o espaço antes de a imagem chegar
Sem width e height, o navegador não sabe o tamanho da imagem até ela chegar. O texto embaixo sobe e depois desce, e a pessoa perde o lugar da leitura. Por isso o web.dev recomenda declarar as duas medidas em toda <img> (web.dev). O CSS ainda pode deixar a imagem flexível, e a proporção fica guardada. O que mede esse pulo é o CLS, assunto do texto sobre estados de carregamento.
Há um caso menos óbvio no mesmo artigo. Numa galeria sem medidas, cada imagem começa com 0 por 0 pixels. Todas parecem caber na tela de uma vez, e o navegador baixa a galeria inteira, mesmo com carregamento lento ligado (web.dev).
O componente <Image /> do Astro preenche largura e altura sozinho para imagens locais (Astro (em inglês)).
Carregamento lento, mas só abaixo da dobra
O atributo loading="lazy" adia o download até a imagem chegar perto da área visível. Ele funciona sem biblioteca de JavaScript. O aviso do próprio web.dev é direto: não use em imagens que provavelmente aparecem na primeira tela, principalmente na que vira o LCP (web.dev). O navegador só adia depois de saber onde a imagem fica na página, e com isso a imagem mais importante da página fica para depois.
O WordPress passou pela prova. Ele passou a aplicar carregamento lento a quase todas as imagens, inclusive às do topo. Num teste em laboratório com o tema Twenty Twenty-One, desligar o carregamento lento deixou o LCP das páginas de arquivo de 13% a 15% mais rápido (web.dev, efeitos de muito carregamento lento). Em compensação, o número de bytes de imagem mais que dobrou.
A correção testada ficou com o melhor dos dois lados. Carregar normalmente só a primeira imagem de destaque e deixar o resto com carregamento lento desfez a perda no LCP e manteve a economia de bytes do comportamento padrão (web.dev).
Prioridade para a imagem principal
Escrever loading="eager" não acelera nada. Isso é só o comportamento normal do navegador, sem atraso extra. Para pedir que uma imagem venha antes das outras, o atributo é fetchpriority="high" (web.dev, API Fetch Priority).
A razão está na ordem de trabalho do Chrome. Imagens na área visível costumam começar com prioridade baixa e só sobem depois que o layout fica pronto. Marcar a principal pula essa espera. Na página do Google Voos, a imagem de fundo com prioridade alta levou o LCP de 2,6 para 1,9 segundo (web.dev).
O atributo também serve para baixar a prioridade. Num carrossel, só a primeira imagem aparece de cara. As outras podem levar fetchpriority="low" para não disputar a rede com ela (web.dev). Os cuidados de design do carrossel estão no texto sobre carrossel no e-commerce.
Como aparece no meu trabalho
No kahue.net, cada imagem tem um papel diferente, e o código segue o papel.
O retrato da página sobre mim aparece com 200 pixels de largura, e o arquivo WebP tem 400. Em tela de alta densidade, o navegador usa os pixels que já existem em vez de esticar a imagem. Como o retrato fica no topo, ele leva width e height, carregamento normal e fetchpriority="high".
Nos cases, como o da Vexor, a imagem grande logo abaixo do título sai em três larguras (768, 1040 e 1400 pixels), com sizes acompanhando a largura da coluna da página. Ela é marcada como eager, porque o componente de imagem do Astro gera loading="lazy" quando nada é dito (referência do Astro (em inglês)). As miniaturas da galeria ficam mais abaixo. Por isso saem em 320 e 640 pixels, com carregamento lento.
Cada miniatura é um link para a tela inteira em WebP, gerada quando o site é compilado. Sem JavaScript, o clique abre a imagem. Com JavaScript, abre a galeria em camada. Antes, esse link levava ao arquivo original em PNG, bem mais pesado.
Uma coisa ainda falta. A capa dos cases pede carregamento normal, mas não pede prioridade alta. Pela referência do Astro (em inglês), a propriedade priority resolve isso de uma vez para imagens do topo. Não medi o efeito dessa mudança, e o texto não atribui número a ela.
Onde as fontes divergem
Os dois artigos do web.dev parecem discordar sobre o risco do carregamento lento. O primeiro diz que, no Chrome para Android com 4G, 97,5% das imagens com carregamento lento terminaram de carregar até 10 milissegundos depois de ficarem visíveis (web.dev). Visto assim, o atraso quase não existe.
O segundo encontrou, nos dados do HTTP Archive, LCP mediano de 2.922 milissegundos em páginas sem carregamento lento e de 3.546 nas que usam (web.dev). Os autores avisam que é correlação, não causa.
As duas coisas cabem juntas. O primeiro número mede imagens fora da tela, que o navegador busca com antecedência enquanto a pessoa rola. O segundo pega o caso em que o carregamento lento caiu na imagem do topo, que não tem antecedência nenhuma.
O erro comum: deixar o CSS encolher a foto
O erro mais frequente é exportar a imagem na largura do arquivo original e deixar o CSS reduzir na tela. Fica bonito em qualquer aparelho, e por isso ninguém percebe. Mas o celular baixa os pixels de um monitor grande para mostrar uma fração deles. O MDN chama isso de desperdício de banda, pago por quem usa o plano de dados do celular. A conferência é simples: abra a aba Rede das ferramentas do navegador numa tela estreita e veja qual arquivo veio.
Fontes
- web.dev, Carregamento lento de imagens no navegador para a Web
- web.dev, Os efeitos de desempenho de muito carregamento lento
- web.dev, Otimizar o carregamento de recursos com a API Fetch Priority
- web.dev, Maior exibição de conteúdo (LCP)
- MDN, Imagens responsivas
- Documentação do Astro, Imagens (em inglês)
- Documentação do Astro, referência de astro:assets (em inglês)
- Nielsen Norman Group, Photos as Web Content (em inglês)
- Nielsen Norman Group, Scrolling and Attention (em inglês)
- Nielsen Norman Group, The Fold Manifesto: Why the Page Fold Still Matters (em inglês)


