Imagens responsivas com srcset e sizes
srcset e sizes permitem que cada dispositivo baixe apenas os pixels de que precisa. Bem configurados, reduzem o peso das imagens no celular a uma fração.
O problema que eles resolvem
Uma mesma imagem é exibida com 360 px de largura em um celular, 768 px em um tablet e 1400 px em um notebook, e ainda em telas com densidades de 1x, 2x ou 3x. Se você serve um único arquivo, ou ele é grande demais para o celular (você desperdiça dados e piora o LCP), ou pequeno demais para o desktop (fica borrado).
Com srcset você descreve quais arquivos tem e com sizes em que tamanho a imagem será exibida. Com essa informação, o navegador —que conhece a largura da janela e a densidade da tela— escolhe o arquivo ideal.
srcset com descritores de largura (w)
É a forma mais útil e a que você deveria usar quase sempre:
<img
src="foto-1280.jpg"
srcset="foto-640.jpg 640w, foto-1280.jpg 1280w, foto-1920.jpg 1920w"
sizes="(min-width: 1024px) 800px, 100vw"
width="1920" height="1080"
alt="Descrição da foto">
Cada entrada é arquivo largura_real_em_pixels seguido de w. O src funciona como fallback para navegadores muito antigos.
O atributo sizes
O sizes indica a largura na tela que a imagem vai ocupar, não a do arquivo. É uma lista de condições de media query com uma largura, e um valor final padrão:
sizes="(min-width: 1024px) 800px, (min-width: 640px) 50vw, 100vw"
Lê-se assim: em telas de pelo menos 1024 px, a imagem ocupa 800 px; entre 640 e 1023 px, metade da janela; abaixo disso, a janela inteira.
O navegador multiplica essa largura pela densidade de pixels e escolhe o menor arquivo que a cobre. Por exemplo, em um celular de 390 px de largura a 3x ele precisará de cerca de 1170 px, então vai escolher foto-1280.jpg.
Erros típicos com sizes
- Omiti-lo. Se você não o colocar, o navegador assume
100vw, e no desktop vai baixar a imagem maior mesmo que ela seja exibida em uma coluna estreita. - Colocar a largura do arquivo. O
sizesdescreve o layout, não os arquivos. - Não bater com o CSS. Se o seu CSS mudar, revise o
sizes. Você pode conferir no DevTools: a propriedadecurrentSrcdo elemento mostra qual arquivo foi escolhido.
Se você usa loading="lazy", os navegadores baseados no Chromium já aceitam sizes="auto" (você pode escrever sizes="auto, 100vw" como fallback), que calcula o valor a partir do layout real. Só funciona em imagens adiadas.
Se não quiser calcular à mão, o gerador de srcset monta o sizes a partir do seu layout e gera as variantes.
srcset com descritores de densidade (x)
Para imagens de tamanho fixo —um avatar de 64 px, um logotipo— basta indicar densidades:
<img src="avatar-64.png" srcset="avatar-64.png 1x, avatar-128.png 2x" width="64" height="64" alt="">
Não combine w e x no mesmo srcset.
Quais larguras gerar
Não é preciso uma variante para cada dispositivo. Uma regra prática é cobrir saltos de 30% a 50% de peso:
| Tipo de imagem | Larguras sugeridas |
|---|---|
| Hero em tela cheia | 640, 960, 1280, 1920, 2560 |
| Imagem de artigo (coluna de ~800 px) | 480, 800, 1200, 1600 |
| Card em grade | 320, 480, 640, 960 |
No ImageZap, ative Variantes responsivas, marque as larguras e o gerador de código escreverá o srcset com os nomes reais dos arquivos.
srcset dentro de picture
Se você também quiser servir vários formatos, cada <source> leva seu próprio srcset e sizes:
<picture>
<source type="image/avif" srcset="foto-640.avif 640w, foto-1280.avif 1280w" sizes="(min-width: 1024px) 800px, 100vw">
<source type="image/webp" srcset="foto-640.webp 640w, foto-1280.webp 1280w" sizes="(min-width: 1024px) 800px, 100vw">
<img src="foto-1280.jpg" srcset="foto-640.jpg 640w, foto-1280.jpg 1280w" sizes="(min-width: 1024px) 800px, 100vw" width="1280" height="720" alt="…">
</picture>
Não esqueça width e height
Os atributos width e height não fixam o tamanho na tela (isso é papel do CSS), mas permitem que o navegador reserve o espaço com a proporção correta antes de a imagem chegar. Assim você evita saltos de layout (CLS). Combine-os com:
img { max-width: 100%; height: auto; }
Perguntas frequentes
Por que o navegador baixa uma imagem maior que a esperada?
Provavelmente por causa da densidade da tela (um celular a 3x precisa do triplo de pixels) ou porque falta o sizes. Confira o currentSrc no DevTools.
O navegador baixa de novo ao redimensionar a janela?
Ele pode baixar uma variante maior se precisar, mas normalmente não desce para uma menor se já tiver uma maior em cache.
Preciso de srcset se uso uma CDN de imagens?
Muitas CDNs geram as variantes para você, mas você continua precisando escrever srcset e sizes (ou usar um componente que faça isso) para que o navegador escolha.
Quantas variantes são demais?
Mais de 5-6 por formato raramente compensa. Cada variante extra é mais trabalho de geração e cache para uma economia marginal.