TLDR
Prefira usar background-image
quando a imagem gabaritar (ou quase) essa lista:
- Não for a maior imagem da página
- Não tenha que ser a primeira a carregar
- Tenha sido previamente comprimida
- For meramente decorativa
- Necessita de uma composição complexa (overlays)
Mas porque? No final não dá tudo no mesmo?
Imagens são conteúdo, mesmo as decorativas, então queremos que elas carreguem o mais rápido que puderem.
A questão do carregamento
A google criou uma métrica pra medir esse carregamento de conteúdo na página - a LCP (Largest Contentful Paint) mede quanto tempo leva pro maior conteúdo da página carregar.
Ela considera imagens, videos e blocos de texto como conteúdo e mede o maior conteúdo em área pois é uma métrica de velocidade percebida de carregamento, afinal, performance é sobre experiência de usuário.
No exemplo abaixo eu carrego 3 imagens em uma página, duas via tag <img>
no HTML e uma via background-image
no CSS.
As imagens tem do HTML pesam 7kb, e 15kb e a do CSS pesa 175kb. Ao inspecionar pela tab Performance do devTools, as imagens do HTML carregaram em paralelo ao CSS, já a terceira imagem carregou apenas quando o arquivo de CSS foi encontrado.
Isso porque pra encontrar a imagem carregada pelo CSS, foi necessário processar todo o arquivo CSS. No vídeo do tweet
abaixo simulei 3g lento no navegador.
As duas imagens do HTML carregam quase que simultaneamente, enquanto a maior do fundo leva bem mais tempo pra começar a carregar.
Controle de prioridade da imagem
Outro ponto também é que a imagem carregada pelo CSS vem com uma prioridade de carregamento menor do que as imagens declaradas já no HTML.
Apesar de imagens serem um recurso com prioridade baixa em relação a outros arquivos, a localização influencia. Você pode conferir sobre esses critérios de prioridade no post sobre a FetchPriority API do web.dev em inglês.
Há casos também que queremos despriorizar o carregamento das imagens, como pra imagens que não aparecem imediatamente no viewport do usuário.
Podemos fazer isso direto pelo HTML usando o atributo loading="lazy"
.
Além disso, usando a tag <picture>
conseguimos carregar imagens com formatos mais leves, otimizados e com fallback usando a tag <picture>
+ <source>
e tamanhos diferentes da mesma imagem dependendo do viewport com os atributos srcset
e sizes
.
Picture com source | Img com srcset |
---|---|
"Po mas então eu NUNCA vou usar background-image"
Calma lá que pra esse tem solução. Caso você realmente precise usar um background
, você pode fazer o preload dele pelo HTML, tomando o cuidado pra fazer após às tags de estilo.
Temos muitos avanços pra imagens via CSS como a função CSS image()
que possuí fallbacks e possibilita uma melhor direção de arte da imagem que só o HTML não oferece, mas em relação à controle de performance o HTML ainda é imbatível.
Top comments (6)
Muito bom!! Eu acho que é um dos conhecimentos básicos (talvez nem tão básicos assim(?)) de web mais subestimados por aí...
Pior que tive tive que elaborar muito o lado de Core Web Vitals e depois voltar pros rudimentares sobre CSS / HTML pra chegar nesse tópico, queria ver mais sobre!
Eu aprendi muito com os artigos da web.dev
web.dev/optimize-lcp/#slow-resourc...
Eu não ironicamente tava precisando desse artigo
Pooo que dahora!
Que conteúdo daora! Um detalhe básico que muda tudo! 😮😮😮😮
Sempre muito bons seus conteúdos meu mano, mandou bem