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.