Quando usar a tag <img> e a propriedade background-image?
Tags: css, beginners, braziliandevs, webdev
Published: 2023-09-21 12:00:00

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

<br />

---

<br />

## 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)](https://web.dev/lcp/) 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2ht6keg90zr8t4jpz35x.png)

&nbsp;

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 `<img>` no HTML e uma via `background-image`](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v0n7u2vkdobyz1vah0sq.png)

&nbsp;

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
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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/80mx5apycsp9v5k11z9c.png)

&nbsp;

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.

{% twitter 1677103746315059200 %}

<br />

---

<br />

## 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](https://web.dev/fetch-priority/#resource-priority).


![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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oioapg7t1zsl3ljuoobk.png)

&nbsp;

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"`](https://web.dev/browser-level-image-lazy-loading/#the-loading-attribute).

![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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xq8myaa94ojcs6la8k7s.png)

&nbsp;

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`](https://web.dev/codelab-specifying-multiple-slot-widths/).

&nbsp;

| Picture com source | Img com srcset |
| ---- | ---- |
| ![Tag picture contendo diferentes sources](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vqu7vno9shzk5v0tw6bu.png) | ![Imagens com srcset carregando diversos tamanhos](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6yk7olhtpsrtkag7qmtn.png) |

<br />

---

<br />

## "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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fqykw3fnzxk566zag2rx.png)

&nbsp;

Temos muitos avanços pra imagens via CSS como a [função CSS `image()`](https://developer.mozilla.org/en-US/docs/Web/CSS/image/image#accessibility_concerns) 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.