Performance da imagem

As imagens geralmente são o recurso mais pesado e mais predominante na Web. Como resultado, otimizar imagens pode melhorar significativamente a performance no 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 com tamanho adequado para o dispositivo dele.

É possível adicionar imagens 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 quando se trata de usar recursos de imagem é exibir a imagem no tamanho correto. Nesse caso, o termo tamanho se refere às dimensões de uma imagem. Sem considerar outras variáveis, uma imagem exibida em um contêiner de 500 por 500 pixels tem o tamanho ideal de 500 por 500 pixels. Por exemplo, usar uma imagem quadrada de 1.000 pixels significa que ela é duas vezes maior que o necessário.

No entanto, há muitas variáveis envolvidas na escolha do tamanho adequado da imagem, fazendo com que essa tarefa seja 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.

Exibir tudo em resolução mais alta teria tornado o texto e as imagens significativamente menores, metade do tamanho anterior para ser exato. Em vez disso, 1 pixel se tornou dois pixels de dispositivo. Isso é chamado de proporção de pixels do dispositivo (DPR, na sigla em inglês). O iPhone 4 — e muitos modelos de iPhone lançados depois dele — tinha uma DPR de 2.

Voltando ao exemplo anterior, se o dispositivo tiver uma DPR de 2 e a imagem for exibida em um contêiner de 500 por 500 pixels, uma imagem quadrada de 1.000 pixels (chamada de tamanho intrínseco) agora será o tamanho ideal. Da mesma forma, se o dispositivo tiver uma 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 largura ou densidade de pixels.

<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 pixel para sugerir que o navegador use image-500.png em dispositivos com DPR de 1, image-1000.jpg em dispositivos com DPR de 2 e image-1500.jpg em dispositivos com DPR de 3.

Embora tudo isso possa parecer muito curto, a 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ó funcionaria se você exibir a imagem com o 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 com ela mudam de acordo com o dispositivo do usuário.

O atributo sizes permite 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 combinado com os descritores de largura srcset, o navegador pode escolher qual origem de imagem é a 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 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 indica 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 tem 1.000 pixels de largura.

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

Assim, o navegador pode combinar essas informações com a lista de origens de imagens srcset para encontrar a imagem ideal. Por exemplo, se o usuário estiver em um dispositivo móvel com 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. Nesse 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 diversos formatos de arquivos de imagem. Formatos de imagem modernos, como WebP e AVIF, podem oferecer uma compactação melhor do que PNG ou JPEG, diminuindo o tamanho do arquivo de imagem e, portanto, fazendo o download em menos tempo. Ao disponibilizar imagens em formatos modernos, é possível reduzir o tempo de carregamento de um recurso, o que pode resultar em uma Maior exibição de conteúdo (LCP).

WebP é um formato com ampla compatibilidade que funciona em todos os navegadores modernos. O formato WebP geralmente 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 ao usar compressã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 um suporte tão amplo quanto o WebP, ele tem um suporte razoável em todos os navegadores. O AVIF oferece suporte à compressão com e sem perda, e os testes mostraram uma economia maior que 50% quando comparado com JPEG em alguns casos. O AVIF também oferece os recursos Wide Color Gamut (WCG) e de High Dynamic Range (HDR).

Compactação

Quando estão relacionadas a imagens, há dois tipos de compactação:

  1. Compressão com perda
  2. Compressão sem perdas

A compressão com perda reduz a precisão da imagem por meio da quantização, e outras informações de cor podem ser descartadas com o uso da chroma subamostragem. A compactação com perda é mais eficaz em imagens de alta densidade com muito ruído e cores, geralmente fotos ou imagens com conteúdo semelhante. Isso ocorre porque os artefatos produzidos por compactação com perda têm muito menos chances de serem notados nessas imagens detalhadas. No entanto, a compressão com perda pode ser menos eficaz com imagens que contêm bordas nítidas, como desenho, detalhes simples ou texto. A compactação com perdas pode ser aplicada a imagens JPEG, WebP e AVIF.

A compactação sem perdas reduz o tamanho do arquivo ao compactar uma imagem sem perda de dados. A compressã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. Ao compactar, não há uma configuração universal adequada para todos os casos. A abordagem recomendada seria testar diferentes níveis de compactação até encontrar um bom equilíbrio entre a qualidade da imagem e o tamanho do arquivo. Alguns serviços avançados de otimização de imagens fazem isso automaticamente, mas podem não ser financeiramente viáveis para todos os usuários.

O elemento <picture>

O elemento <picture> oferece maior flexibilidade na especificação de várias candidatas 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>

Ao usar elementos <source> no elemento <picture>, é possível adicionar suporte a imagens AVIF e WebP, mas usar 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, ele a usará. Caso contrário, o navegador vai avançar para o próximo elemento <source> especificado. No snippet HTML anterior, o formato AVIF tem prioridade sobre o WebP, voltando para o formato JPEG se nenhum deles tiver suporte.

Um elemento <picture> requer 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 oferece suporte aos atributos media, srcset e sizes. De forma semelhante ao exemplo <img> anterior, elas indicam ao navegador qual imagem selecionar em diferentes janelas de visualização.

<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, a DPR do dispositivo é usada como a condição de mídia. Qualquer dispositivo com uma 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 maior que 768 pixels, a imagem candidata a ser exibida será exibida 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ê pode ter um controle mais preciso sobre qual imagem usar.

Isso é ilustrado na tabela abaixo, 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 uma 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 externo de 500 pixels de largura. Por outro lado, os usuários de dispositivos móveis com uma DPR de 3 fazem o download de um image-1500.jpg potencialmente maior, a mesma imagem usada em dispositivos desktop com uma DPR de 3.

<picture>
  <source
    media="(min-width: 560px) 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> extra para usar imagens diferentes para dispositivos amplos com uma DPR alta:

Largura da janela de visualização (pixels) 1 DPR 1,5 DPR 2 DPR 3 DPR
320 500.jpg 500.jpg 500.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 outra consulta, é possível ver que image-1000-sm.jpg e image-1500-sm.jpg são exibidos em janelas de visualização pequenas. Essas informações extras permitem compactar ainda mais as imagens, já que os artefatos de compactação não são altamente visíveis nesse tamanho e densidade, sem comprometer a qualidade da imagem em dispositivos desktop.

Como alternativa, ao ajustar os atributos srcset e media, você pode evitar a veiculação de imagens grandes em janelas de visualização pequenas:

<picture>
  <source
    media="(min-width: 560px)"
    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 HTML anterior, os descritores de largura foram removidos em favor dos descritores de proporção de pixels do dispositivo. As imagens exibidas 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 usar 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ê precisa ter? Como muitos problemas de engenharia, a resposta tende a ser "depende".

Pode ser tentador ter tantas variações para oferecer o melhor ajuste, mas todas as variantes de imagem adicionais têm um custo e fazem uso menos eficiente do cache do navegador. Com apenas uma variante, todos os usuários recebem a mesma imagem e, por isso, ela pode ser armazenada em cache com muita eficiência.

Por outro lado, se houver muitas variações, cada variante vai exigir outra entrada de cache. Os custos de servidor podem aumentar e prejudicar o desempenho se a entrada de cache da variante tiver expirado e a imagem precisar ser buscada novamente no servidor de origem.

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

Disponibilize 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 seu 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 HTML anterior é uma versão simplificada do código que você pode adicionar 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á veiculada. Caso contrário, se o cabeçalho Accept incluir image/webp, a imagem WebP será exibida. Se nenhuma dessas condições for verdadeira, a imagem JPEG será veiculada.

É possível modificar respostas com base no conteúdo do cabeçalho da 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.

Esse comportamento não é diferente do que você encontraria em uma rede de fornecimento de conteúdo (CDN) de imagens. CDNs de imagens são soluções excelentes para otimizar imagens e enviar o formato ideal com base no dispositivo e navegador do usuário.

O segredo é encontrar um equilíbrio, gerar um número razoável de imagens candidatas e medir o impacto na experiência do usuário. Imagens diferentes podem fornecer 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 em miniatura em uma página de informações do produto de e-commerce.

Carregamento lento

É possível instruir o navegador a fazer o carregamento lento de imagens quando elas aparecerem na janela de visualização usando o atributo loading. Um valor de atributo de lazy instrui o navegador a não fazer o download da imagem até que ela esteja na janela de visualização ou perto dela. Isso economiza largura de banda, permitindo que o navegador priorize os recursos necessários para renderizar o conteúdo essencial que já está na janela de visualização.

decoding

O atributo decoding informa ao navegador como ele precisa decodificar a imagem. Um valor de async informa ao navegador que a imagem pode ser decodificada de forma assíncrona, possivelmente melhorando o tempo para renderizar outro conteúdo. Um valor de sync informa ao navegador que a imagem precisa ser apresentada ao mesmo tempo que 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 são compatíveis com a compressão sem perdas?

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

Quais formatos de imagem são compatíveis com a compactação com perdas?

GIF.
Tente novamente. Embora o formato GIF seja compatível apenas com uma paleta limitada de 256 cores, a codificação com perda precisa ser feita antes da conversão para 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 forem aplicados à página
Tente novamente.
A largura intrinsic da imagem, ou seja, as dimensões da própria imagem.
Correto.

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

Lógica que expressa qual candidato especificado em um srcset do elemento <img> precisa ser carregado, de acordo com as dimensões da janela de visualização atual do usuário.
Correto.
A largura intrinsic da imagem a ser carregada do atributo srcset do elemento <img>.
Tente novamente.

A seguir: desempenho do vídeo

Embora as imagens possam ser o tipo de mídia mais comum usado na Web, elas são longe de serem as únicas que você precisa ter em mente quando se trata de desempenho. Vídeo é outro tipo comum de mídia usado na Web e vem com as próprias considerações de desempenho. No próximo módulo deste curso, você vai conhecer algumas técnicas relacionadas à otimização de vídeos e como carregá-los de maneira eficiente.