As imagens costumam ser o recurso mais pesado e mais comum na Web. Por isso, otimizar imagens pode melhorar significativamente a performance do seu site. Na maioria dos casos, otimizar imagens significa reduzir o tempo de rede enviando menos bytes, mas também é possível otimizar a quantidade de bytes enviados ao usuário veiculando imagens dimensionadas corretamente para o dispositivo dele.
As imagens podem ser adicionadas a uma página usando os elementos <img>
ou <picture>
ou a propriedade background-image
do CSS.
Tamanho da imagem
A primeira otimização que você pode fazer ao usar recursos de imagem é mostrar a imagem no tamanho correto. Nesse caso, o termo tamanho se refere às dimensões de uma imagem. Considerando que não há outras variáveis, uma imagem exibida em um contêiner de 500 pixels por 500 pixels teria o tamanho ideal de 500 pixels por 500 pixels. Por exemplo, usar uma imagem quadrada de 1.000 pixels significa que ela é duas vezes maior do que o necessário.
No entanto, há muitas variáveis envolvidas na escolha do tamanho adequado da imagem, o que torna a tarefa de escolher o tamanho adequado em todos os casos bastante complicada. Em 2010, quando o iPhone 4 foi lançado, a resolução da tela (640 x 960) era o dobro da do iPhone 3 (320 x 480). No entanto, o tamanho físico da tela do iPhone 4 permaneceu aproximadamente o mesmo do iPhone 3.
Mostrar tudo na resolução mais alta teria diminuído significativamente o texto e as imagens, exatamente pela metade do tamanho anterior. Em vez disso, um pixel se tornou dois pixels do dispositivo. Isso é chamado de proporção de pixels do dispositivo (DPR). O iPhone 4 e muitos modelos lançados depois dele tinham uma DPR de 2.
Retomando o exemplo anterior, se o dispositivo tiver uma DPR de 2 e a imagem for exibida em um contêiner de 500 x 500 pixels, uma imagem quadrada de 1.000 pixels (chamada de tamanho intrínseco) será o tamanho ideal. Da mesma forma, se o dispositivo tiver um DPR de 3, uma imagem quadrada de 1.500 pixels será o tamanho ideal.
srcset
O elemento <img>
é compatível com o atributo srcset
, que permite especificar uma
lista de possíveis origens de imagem que o navegador pode usar. Cada origem de imagem especificada
precisa incluir o URL da imagem e um descritor de densidade de pixels de largura ou.
<img
alt="An image"
width="500"
height="500"
src="/image-500.jpg"
srcset="/image-500.jpg 1x, /image-1000.jpg 2x, /image-1500.jpg 3x"
>
O snippet HTML anterior usa o descritor de densidade de pixels para sugerir ao navegador
usar image-500.png
em dispositivos com um DPR de 1, image-1000.jpg
em dispositivos
com um DPR de 2 e image-1500.jpg
em dispositivos com um DPR de 3.
Embora tudo isso possa parecer simples, a DPR de uma tela não é a única consideração ao escolher a imagem ideal para uma determinada página. O layout da página é outra consideração.
sizes
A solução anterior só funciona se você mostrar a imagem no mesmo tamanho de pixel CSS em todas as janelas de visualização. Em muitos casos, o layout de uma página e o tamanho do contêiner mudam dependendo do dispositivo do usuário.
Com o atributo sizes
, é possível especificar um conjunto de tamanhos de origem, em que cada
tamanho consiste em uma condição de mídia e um valor. O atributo sizes
descreve o tamanho de exibição pretendido da imagem em pixels CSS. Quando combinados
com os descritores de largura srcset
, o navegador pode escolher qual origem de imagem
é melhor para o dispositivo do usuário.
<img
alt="An image"
width="500"
height="500"
src="/image-500.jpg"
srcset="/image-500.jpg 500w, /image-1000.jpg 1000w, /image-1500.jpg 1500w"
sizes="(min-width: 768px) 500px, 100vw"
>
No snippet HTML anterior, o atributo srcset
especifica uma lista de candidatos a imagem que o navegador pode escolher, separados por vírgulas. Cada candidato na lista consiste no URL da imagem, seguido por uma sintaxe que denota a largura intrínseca da imagem. O tamanho intrínseco de uma imagem são as dimensões dela. Por exemplo, um descritor de 1000w
indica que a largura intrínseca da imagem é de 1.000 pixels.
Com essas informações, o navegador avalia a condição de mídia no atributo sizes
e, nesse caso, recebe a instrução de que, se a largura da janela de visualização do dispositivo exceder 768 pixels, a imagem será mostrada com uma largura de 500 pixels. Em dispositivos menores, a imagem é exibida em 100vw
ou na largura total da janela de visualização.
Em seguida, o navegador pode combinar essas informações com a lista de fontes de imagens srcset
para encontrar a imagem ideal. Por exemplo, se o usuário estiver em um dispositivo móvel
com uma largura de tela de 320 pixels e um DPR de 3, a imagem será exibida
em 320 CSS pixels x 3 DPR = 960 device pixels
. Neste exemplo, a imagem de tamanho mais próximo seria image-1000.jpg
, que tem uma largura intrínseca de 1.000 pixels (1000w
).
Formatos de arquivo
Os navegadores são compatíveis com vários formatos de arquivo de imagem diferentes. Formatos de imagem modernos, como WebP e AVIF, podem oferecer uma compactação melhor do que PNG ou JPEG, reduzindo o tamanho do arquivo de imagem e, portanto, levando menos tempo para fazer o download. Ao veicular imagens em formatos modernos, você pode reduzir o tempo de carregamento de um recurso, o que pode resultar em uma Maior exibição de conteúdo (LCP) menor.
O WebP é um formato amplamente aceito que funciona em todos os navegadores modernos. O WebP geralmente tem uma compactação melhor do que JPEG, PNG ou GIF, oferecendo com perda e sem perda. O WebP também é compatível com transparência do canal Alfa, mesmo ao usar compactação com perda, um recurso que o codec JPEG não oferece.
O AVIF é um formato de imagem mais recente e, embora não seja tão amplamente compatível quanto o WebP, ele tem suporte razoavelmente decente em todos os navegadores. O AVIF é compatível com compactação com e sem perda, e testes mostraram uma economia de mais de 50% em comparação com o JPEG em alguns casos. O AVIF também oferece recursos de ampla gama de cores (WCG) e High Dynamic Range (HDR).
Compactação
No caso de imagens, há dois tipos de compactação:
A compactação com perda reduz a acurácia da imagem por quantização, e outras informações de cor podem ser descartadas usando subamostragem de croma. A compactação com perdas é mais eficaz em imagens de alta densidade com muito ruído e cores, geralmente fotos ou imagens com conteúdo semelhante. Isso acontece porque os artefatos produzidos pela compactação com perdas têm muito menos chances de serem notados em imagens tão detalhadas. No entanto, a compactação com perdas pode ser menos eficaz com imagens que contêm bordas nítidas, como arte linear, detalhes igualmente nítidos ou texto. A compactação com perda pode ser aplicada a imagens JPEG, WebP e AVIF.
A compactação sem perdas reduz o tamanho do arquivo compactando uma imagem sem perda de dados. A compactação sem perdas descreve um pixel com base na diferença dos pixels vizinhos. A compactação sem perda é usada para os formatos de imagem GIF, PNG, WebP e AVIF.
É possível compactar as imagens usando o Squoosh, o ImageOptim ou um serviço de otimização de imagens. Não há uma configuração universal adequada para todos os casos. A abordagem recomendada é testar diferentes níveis de compactação até encontrar um bom compromisso entre qualidade da imagem e tamanho do arquivo. Alguns serviços avançados de otimização de imagens fazem isso automaticamente, mas podem não ser viáveis financeiramente para todos os usuários.
O elemento <picture>
O elemento <picture>
oferece mais flexibilidade na especificação de vários candidatos a imagens:
<picture>
<source type="image/avif" srcset="image.avif">
<source type="image/webp" srcset="image.webp">
<img
alt="An image"
width="500"
height="500"
src="/image.jpg"
>
</picture>
Ao usar elementos <source>
no elemento <picture>
, você pode adicionar suporte a imagens AVIF e WebP, mas voltar a formatos de imagem legados mais compatíveis se o navegador não for compatível com formatos modernos. Com essa abordagem, o navegador escolhe o primeiro elemento <source>
especificado que corresponde. Se for possível renderizar a imagem nesse formato, ela será usada. Caso contrário, o navegador
passa para o próximo elemento <source>
especificado. No snippet HTML anterior, o formato AVIF tem prioridade sobre o WebP, voltando para o JPEG se nenhum dos dois for compatível.
Um elemento <picture>
exige um elemento <img>
aninhado dentro dele. Os atributos alt
, width
e height
são definidos no <img>
e usados
independente de qual <source>
é selecionado.
O elemento <source>
também é compatível com os atributos media
, srcset
e sizes
. Assim como no exemplo de <img>
, eles indicam ao navegador qual imagem selecionar em diferentes viewports.
<picture>
<source
media="(min-resolution: 1.5x)"
srcset="/image-1000.jpg 1000w, /image-1500.jpg 1500w"
sizes="(min-width: 768px) 500px, 100vw"
>
<img
alt="An image"
width="500"
height="500"
src="/image-500.jpg"
>
</picture>
O atributo media
usa uma condição de mídia. No exemplo anterior, o DPR do dispositivo é usado como a condição de mídia. Qualquer dispositivo com um DPR maior ou igual a 1,5 usaria o primeiro elemento <source>
. O elemento <source>
informa ao navegador que, em dispositivos com uma janela de visualização mais larga que 768 pixels, a
imagem candidata selecionada é mostrada com 500 pixels de largura. Em dispositivos menores,
isso ocupa toda a largura da janela de visualização. Ao combinar os atributos media
e srcset
, você tem um controle mais refinado sobre qual imagem usar.
Isso é ilustrado na tabela a seguir, em que várias larguras de janela de visualização e proporções de pixels do dispositivo são avaliadas:
Largura da janela de visualização (pixels) | 1 DPR | 1,5 DPR | 2 DPR | 3 DPR |
---|---|---|---|---|
320 | 500.jpg | 500.jpg | 500.jpg | 1000.jpg |
480 | 500.jpg | 500.jpg | 1000.jpg | 1500.jpg |
560 | 500.jpg | 1000.jpg | 1000.jpg | 1500.jpg |
1024 | 500.jpg | 1000.jpg | 1000.jpg | 1500.jpg |
1.920 | 500.jpg | 1000.jpg | 1000.jpg | 1500.jpg |
Dispositivos com um DPR de 1 fazem o download da imagem image-500.jpg
, incluindo a maioria dos usuários de computadores, que veem a imagem em um tamanho extrínseco de 500 pixels de largura. Por outro lado, usuários de dispositivos móveis com um DPR de 3 baixam um image-1500.jpg
potencialmente maior, a mesma imagem usada em dispositivos desktop com um DPR de 3.
<picture>
<source
media="(min-width: 561px) and (min-resolution: 1.5x)"
srcset="/image-1000.jpg 1000w, /image-1500.jpg 1500w"
sizes="(min-width: 768px) 500px, 100vw"
>
<source
media="(max-width: 560px) and (min-resolution: 1.5x)"
srcset="/image-1000-sm.jpg 1000w, /image-1500-sm.jpg 1500w"
sizes="(min-width: 768px) 500px, 100vw"
>
<img
alt="An image"
width="500"
height="500"
src="/image-500.jpg"
>
</picture>
Neste exemplo, o elemento <picture>
é ajustado para incluir um elemento <source>
adicional e usar imagens diferentes para dispositivos largos com um DPR alto:
Largura da janela de visualização (pixels) | 1 DPR | 1,5 DPR | 2 DPR | 3 DPR |
---|---|---|---|---|
320 | 500.jpg | 500.jpg | 1000-sm.jpg | 1000-sm.jpg |
480 | 500.jpg | 500.jpg | 1000-sm.jpg | 1500-sm.jpg |
560 | 500.jpg | 1000-sm.jpg | 1000-sm.jpg | 1500-sm.jpg |
1024 | 500.jpg | 1000.jpg | 1000.jpg | 1500.jpg |
1.920 | 500.jpg | 1000.jpg | 1000.jpg | 1500.jpg |
Com essa consulta adicional, é possível ver que image-1000-sm.jpg
e image-1500-sm.jpg
são mostrados em pequenas janelas de visualização. Essas informações extras permitem compactar ainda mais as imagens, já que os artefatos de compactação não são muito visíveis nesse tamanho e densidade, sem comprometer a qualidade da imagem em dispositivos desktop.
Como alternativa, ajuste os atributos srcset
e media
para evitar veicular imagens grandes em janelas de visualização pequenas:
<picture>
<source
media="(min-width: 561px)"
srcset="/image-500.jpg, /image-1000.jpg 2x, /image-1500.jpg 3x"
>
<source
media="(max-width: 560px)"
srcset="/image-500.jpg 1x, /image-1000.jpg 2x"
>
<img
alt="An image"
width="500"
height="500"
src="/image-500.jpg"
>
</picture>
No snippet de HTML anterior, os descritores de largura foram removidos em favor
dos descritores de proporção de pixels do dispositivo. As imagens veiculadas em um dispositivo móvel são limitadas a /image-500.jpg
ou /image-1000.jpg
, mesmo em dispositivos com um DPR de 3.
Como gerenciar a complexidade
Ao trabalhar com imagens responsivas, você pode ter muitas variações de tamanho e formatos diferentes para cada imagem. No exemplo anterior, as variações para cada tamanho são usadas, mas excluem AVIF e WebP. Quantas variantes você deve ter? Como muitos problemas de engenharia, a resposta tende a ser "depende".
Embora seja tentador ter o máximo de variações para oferecer o melhor ajuste, cada variante de imagem adicional tem um custo e torna o uso do cache do navegador menos eficiente. Com apenas uma variante, todos os usuários recebem a mesma imagem, o que permite um armazenamento em cache muito eficiente.
Por outro lado, se houver muitas variações, cada uma delas vai exigir outra entrada de cache. Os custos do servidor podem aumentar e prejudicar o desempenho se a entrada de cache da variante expirar e a imagem precisar ser buscada novamente no servidor de origem.
Além disso, o tamanho do documento HTML aumenta com cada variação. Você pode acabar enviando vários kilobytes de HTML para cada imagem.
Veicular imagens com base no cabeçalho da solicitação Accept
O cabeçalho de solicitação HTTP Accept
informa ao servidor quais tipos de conteúdo o navegador do usuário entende. Essas informações podem ser usadas pelo servidor para veicular
o formato de imagem ideal sem adicionar bytes extras às respostas HTML.
if (request.headers.accept) {
if (request.headers.accept.includes('image/avif')) {
return reply.from('image.avif');
} else if (request.headers.accept.includes('image/webp')) {
return reply.from('image.webp');
}
}
return reply.from('image.jpg');
O snippet de HTML anterior é uma versão simplificada do código que pode ser adicionado ao
back-end JavaScript do servidor para escolher e veicular o formato de imagem ideal.
Se o cabeçalho da solicitação Accept
incluir image/avif
, a imagem AVIF será
fornecida. Caso contrário, se o cabeçalho Accept
incluir image/webp
, a imagem WebP será veiculada. Se nenhuma dessas condições for verdadeira, a imagem JPEG será
fornecida.
É possível modificar as respostas com base no conteúdo do cabeçalho de solicitação Accept
em quase todos os tipos de servidores da Web. Por exemplo, é possível reescrever solicitações de imagens em servidores Apache com base no cabeçalho Accept
usando mod_rewrite
.
Isso não é diferente do comportamento que você encontraria em uma rede de fornecimento de conteúdo (CDN) de imagens. As CDNs de imagens são excelentes soluções para otimizar imagens e enviar o formato ideal com base no dispositivo e no navegador do usuário.
O ideal é encontrar um equilíbrio, gerar um número razoável de candidatos de imagem e medir o impacto na experiência do usuário. Imagens diferentes podem gerar resultados diferentes, e as otimizações aplicadas a cada uma delas dependem do tamanho na página e dos dispositivos usados pelos usuários. Por exemplo, uma imagem principal de largura total pode exigir mais variantes do que imagens em miniatura em uma página de listagem de produtos de e-commerce.
Carregamento lento
É possível instruir o navegador a carregar imagens de forma lenta quando elas aparecem na
janela de visualização usando o atributo loading
. Um valor de atributo lazy
informa ao
navegador para não fazer o download da imagem até que ela esteja na (ou perto da) janela de visualização. Isso economiza largura de banda, permitindo que o navegador priorize os recursos necessários para renderizar o conteúdo crítico que já está na janela de visualização.
decoding
O atributo decoding
informa ao navegador como decodificar a imagem. Um valor de async
informa ao navegador que a imagem pode ser decodificada de forma assíncrona, possivelmente melhorando o tempo de renderização de outros conteúdos. Um valor de sync
informa ao
navegador que a imagem deve ser apresentada ao mesmo tempo que outros conteúdos.
O valor padrão de auto
permite que o navegador decida o que é melhor para o usuário.
Demonstrações de imagens
Teste seus conhecimentos
Quais formatos de imagem são compatíveis com a compactação sem perda?
Quais formatos de imagem são compatíveis com a compactação com perda?
O que o descritor de largura (por exemplo, 1000w
) informa ao navegador sobre uma opção de imagem especificada em um atributo srcset
?
O que o atributo sizes
informa ao navegador sobre um elemento
<img>
a que ele é aplicado?
<img>
srcset
do elemento deve ser carregado,
considerando as dimensões da janela de visualização atual do usuário.
srcset
do elemento
<img>
.
Próximo: performance do vídeo
Embora as imagens sejam o tipo de mídia mais comum usado na Web, elas não são as únicas que você precisa considerar quando se trata de performance. O vídeo é outro tipo comum de mídia usado na Web e tem considerações de performance próprias. No próximo módulo deste curso, você vai conhecer algumas técnicas para otimizar vídeos e carregá-los com eficiência.