Performance da imagem

As imagens geralmente são o recurso mais pesado e mais comum na Web. Como resultado, a otimização de 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 você também pode otimizar a quantidade de bytes enviados ao usuário apresentando imagens com o tamanho adequado para o dispositivo do usuário.

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 realizar ao usar recursos de imagem é exibir 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 x 500 pixels teria o tamanho ideal de 500 x 500 pixels. Por exemplo, usar uma imagem quadrada de 1.000 pixels significa que a imagem é duas vezes maior do que o necessário.

No entanto, há muitas variáveis envolvidas na escolha do tamanho de imagem adequado, o que torna a tarefa de escolher o tamanho de imagem 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 reduzido significativamente o texto e as imagens, metade do tamanho anterior, para ser exato. Em vez disso, um pixel tornou-se dois pixels do dispositivo. Isso é chamado de proporção de pixels do dispositivo (DPR, na sigla em inglês). O iPhone 4 e muitos modelos lançados depois dele tinham um DPR de 2.

Voltando ao exemplo anterior, se o dispositivo tiver um 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> oferece suporte ao 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 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 de HTML anterior usa o descritor de densidade de pixels para sugerir ao navegador que use 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 pareça simples, o DPR de uma tela não é a única consideração na escolha da 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 viewports. Em muitos casos, o layout de uma página e o tamanho do contêiner mudam de acordo com o dispositivo do usuário.

O atributo sizes permite especificar um conjunto de tamanhos de origem, em que cada tamanho de origem 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 combinado com os descritores de largura srcset, o navegador pode escolher qual fonte 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 de HTML anterior, o atributo srcset especifica uma lista de candidatos de 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.

Usando essas informações, o navegador avalia a condição de mídia no atributo sizes e, nesse caso, é instruído que, se a largura da janela de visualização do dispositivo ultrapassar 768 pixels, a imagem será mostrada com uma largura de 500 pixels. Em dispositivos menores, a imagem é exibida em 100vw, ou a largura total da viewport.

O navegador pode combinar essas informações com a lista de fontes de imagem 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á mostrada em 320 CSS pixels x 3 DPR = 960 device pixels. Neste exemplo, a imagem mais próxima seria image-1000.jpg, que tem uma largura intrínseca de 1.000 pixels (1000w).

Formatos de arquivo

Os navegadores oferecem suporte a vários formatos de arquivo de imagem. Formatos de imagem modernos, como WebP e AVIF, podem oferecer uma compactação melhor do que PNG ou JPEG, tornando o tamanho do arquivo de imagem menor e, portanto, levando menos tempo para fazer o download. Ao exibir 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 com amplo suporte que funciona em todos os navegadores modernos. O WebP muitas vezes tem uma compactação melhor do que JPEG, PNG ou GIF, oferecendo compactação com perda e sem perda. O WebP também oferece suporte à transparência do canal Alfa mesmo quando usando 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 tenha o mesmo suporte do WebP, ele tem um suporte razoável em vários navegadores. O AVIF oferece suporte à compactação com e sem perda, e os 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, na sigla em inglês) e intervalo dinâmico alto (HDR, na sigla em inglês).

Compactação

No caso de imagens, há dois tipos de compactação:

  1. Compressão com perdas
  2. Compactação sem perdas

A compactação com perda funciona reduzindo a precisão da imagem por quantização, e outras informações de cor podem ser descartadas usando a subamostragem de croma. A compactação com perda é mais eficaz em imagens de alta densidade com muito ruído e cores, normalmente fotos ou imagens com conteúdo semelhante. Isso ocorre porque os artefatos produzidos pela compactação com perdas têm muito menos probabilidade 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 nítidos semelhantes 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 em relação aos pixels vizinhos. A compactação sem perda é usada para os formatos de imagem GIF, PNG, WebP e AVIF.

É possível compactar suas imagens usando o Squoosh, o ImageOptim ou um serviço de otimização de imagens. Ao compactar, 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 a qualidade da imagem e o tamanho do arquivo. Alguns serviços avançados de otimização de imagens podem fazer isso automaticamente, mas talvez não sejam financeiramente viáveis para todos os usuários.

O elemento <picture>

O elemento <picture> oferece mais flexibilidade ao especificar vários candidatos de imagem:

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

Quando você usa elementos <source> no elemento <picture>, é possível adicionar suporte a imagens AVIF e WebP, mas voltar para formatos de imagem legados mais compatíveis se o navegador não oferecer suporte a formatos modernos. Com essa abordagem, o navegador escolhe o primeiro elemento <source> especificado que corresponde. Se ele puder renderizar a imagem nesse formato, ela será usada. Caso contrário, o navegador passa para o próximo elemento <source> especificado. No snippet de HTML anterior, o formato AVIF tem prioridade sobre o formato WebP, voltando para o formato JPEG se nenhum deles for compatível.

Um elemento <picture> requer um elemento <img> aninhado nele. Os atributos alt, width e height são definidos no <img> e usados independentemente de qual <source> for selecionado.

O elemento <source> também oferece suporte aos atributos media, srcset e sizes. Assim como no exemplo de <img> anterior, 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 viewport maior que 768 pixels, a imagem candidata selecionada é exibida com 500 pixels de largura. Em dispositivos menores, isso ocupa toda a largura da viewport. Ao combinar os atributos media e srcset, você pode ter um controle mais preciso sobre qual imagem usar.

Isso é ilustrado na tabela a seguir, em que várias larguras de viewport 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 visualizam a imagem com um tamanho externo de 500 pixels de largura. Por outro lado, os usuários de dispositivos móveis com um DPR de 3 fazem o download de uma image-1500.jpg potencialmente maior, a mesma imagem usada em dispositivos de computador 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 outro elemento <source> para usar imagens diferentes em 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 extra, é possível ver que image-1000-sm.jpg e image-1500-sm.jpg são exibidos em visualizações pequenas. Essas informações extras permitem compactar as imagens ainda mais, 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 de computador.

Como alternativa, ajustando os atributos srcset e media, você pode evitar a exibição de 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 DPR 3.

Como gerenciar a complexidade

Ao trabalhar com imagens responsivas, você pode encontrar muitas variações de tamanho e formatos diferentes para cada imagem. No exemplo anterior, as variações de cada tamanho são usadas, mas excluem AVIF e WebP. Quantas variantes você precisa ter? Como em muitos problemas de engenharia, a resposta tende a ser "depende".

Pode ser tentador ter muitas variações para oferecer a melhor opção, mas cada variante de imagem adicional tem um custo e faz um uso menos eficiente do cache do navegador. Com apenas uma variante, todos os usuários recebem a mesma imagem, para que ela possa ser armazenada em cache de maneira 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 a performance se a entrada de cache da variante tiver expirado e a imagem precisar ser buscada novamente do servidor de origem.

Além disso, o tamanho do documento HTML aumenta com cada variação. Você pode enviar vários kilobytes de HTML para cada imagem.

Servir imagens com base no cabeçalho da solicitação Accept

O cabeçalho da 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 exibir 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 você pode adicionar ao back-end JavaScript do servidor para escolher e fornecer o formato de imagem ideal. Se o cabeçalho Accept da solicitação incluir image/avif, a imagem AVIF será encaminhada. 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á enviada.

É possível modificar as respostas com base no conteúdo do cabeçalho de solicitação Accept em quase todos os tipos de servidor da Web. Por exemplo, é possível reescrever solicitações de imagem em servidores Apache com base no cabeçalho Accept usando mod_rewrite.

Isso é semelhante ao comportamento que você encontraria em uma rede de fornecimento de conteúdo de imagem (CDN). 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 segredo é encontrar um equilíbrio, gerar um número razoável de candidatos a imagem e medir o impacto na experiência do usuário. Imagens diferentes podem gerar resultados diferentes, e as otimizações aplicadas a cada imagem dependem do tamanho dela na página e dos dispositivos que os usuários estão usando. Por exemplo, uma imagem principal de largura total pode exigir mais variantes do que imagens de miniatura em uma página de listagem de produtos de e-commerce.

Carregamento lento

É possível solicitar que o navegador carregue imagens de forma lenta quando elas aparecem no viewport usando o atributo loading. Um valor de atributo de lazy informa ao navegador para não fazer o download da imagem até que ela esteja na viewport (ou perto dela). 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 viewport.

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 outro conteúdo. Um valor de sync informa ao navegador que a imagem precisa ser apresentada ao mesmo tempo que o outro conteúdo. 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 oferecem suporte à compactação sem perdas?

GIF.
Correto!
JPEG.
Tente novamente.
PNG.
Correto!
WebP.
Correto!
AVIF.
Correto!

Quais formatos de imagem oferecem suporte à compactação com perda?

GIF.
Tente novamente. Embora o formato GIF ofereça suporte apenas a uma paleta limitada de 256 cores, a codificação com perda precisa ser feita antes da conversão em GIF.
JPEG.
Correto!
PNG.
Tente novamente.
WebP.
Correto!
AVIF.
Correto!

O que o descritor de largura (por exemplo, 1000w) informa ao navegador sobre uma imagem candidata especificada em um atributo srcset?

A largura extrínseca da imagem, ou seja, as dimensões da imagem no layout depois que os estilos foram aplicados à página.
Tente novamente.
A largura intrinseca da imagem, ou seja, as dimensões da imagem.
Correto!

O que o atributo sizes informa ao navegador sobre um elemento <img> em que ele é aplicado?

Lógica que expressa qual candidato especificado no srcset de um elemento <img> precisa ser carregado, considerando as dimensões da viewport atual do usuário.
Correto!
A largura intrinseca da imagem a ser carregada do atributo srcset do elemento <img>.
Tente novamente.

Próximo: desempenho do vídeo

Embora as imagens sejam o tipo de mídia mais comum usado na Web, elas estão longe de ser as únicas que você precisa considerar quando se trata de desempenho. Vídeos são outro tipo comum de mídia usada na Web e têm suas próprias considerações de desempenho. No próximo módulo deste curso, conheça algumas técnicas para otimizar vídeos e como carregá-los com eficiência.