Quando usar a tag <img> e a propriedade background-image?

Camilo Micheletto - Sep 21 '23 - - Dev Community

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.

LCP (carregamento). Abaixo, uma tabela horizontal com 3 seções nas cores verde, amarelo e vermelha. Até 2.5 segundos de velocidade de carregamento está no verde, até 4 no amarelo e a partir de 4 segundos já está no vermelho

 

No exemplo abaixo eu carrego 3 imagens em uma página, duas via tag <img> no HTML e uma via background-image no CSS.

Imagens em uma página, duas via tag  raw `<img>` endraw  no HTML e uma via  raw `background-image` endraw

 

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.

Aba de Performance no devtools<br>
Na imagem o index.css e as duas imagens carregadas via tag image estão carregando paralelamente, mas a terceira imagem, a do CSS, está carregando só após o CSS

 

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.

Na imagem uma representação gráfica dos arquivos de imagem carregando - com uma tag de prioridade média as imagens do HTML vem na frente, sucedidas pela imagem do CSS com tag de prioridade baixa

 

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".

Foi adicionado loading="lazy" em uma das imagens do HTML e esta está sendo carregada depois da que não está com esse atributo e da carregada via CSS só que com preload no HTML

 

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
Tag picture contendo diferentes sources Imagens com srcset carregando diversos tamanhos

"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.

Preload da imagem acontecendo pela tag link do html

 

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.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .