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:
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?
Quais formatos de imagem oferecem suporte à compactação com perda?
O que o descritor de largura (por exemplo, 1000w
) informa
ao navegador sobre uma imagem candidata especificada em um atributo
srcset
?
O que o atributo sizes
informa ao navegador sobre um
elemento <img>
em que ele é aplicado?
srcset
de um elemento <img>
precisa ser carregado,
considerando as dimensões da viewport atual do usuário.
srcset
do elemento <img>
.
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.