As telas com alta densidade de pixels estão se tornando a norma. Os criadores de conteúdo precisam se adaptar a esse fato. Este é um guia breve sobre como oferecer imagens de alta qualidade na Web hoje, sem polyfills, JavaScript, hacks de CSS e recursos do navegador que ainda não foram implementados totalmente. Em uma palavra: sem mudanças drásticas no fluxo de trabalho.
Hoje, há muitas propostas de imagens responsivas, muitas das quais envolvem
mudanças significativas para o desenvolvedor da Web. O atributo srcset
<img>
da faixa de padrões é difícil de implementar, especialmente com a
complexidade da seleção adicional baseada em viewport de srcset
:
banner-HD.jpeg 2x, banner-phone.jpeg 100w, banner-phone-HD.jpeg 100w 2x
Embora a propriedade CSS image-set
use apenas devicePixelRatio
para
decidir qual imagem carregar, ela ainda força os desenvolvedores a escrever muita
marcação extra para cada imagem.
Outras propostas, como o elemento <picture>
, são ainda mais detalhadas.
Além disso, eles não são padrões, então a disponibilidade
ubíqua deles é ainda maior do que o atributo srcset. O JavaScript
e as soluções do lado do servidor são as únicas outras alternativas, mas essas
abordagens têm as próprias desvantagens, conforme abordado em outros
artigos.
Este artigo aborda vários usos de imagens comumente encontradas na
Web e propõe soluções simples que funcionam em telas com densidades de
pixels altas e comuns. Para os fins desta
discussão, qualquer dispositivo que informe window.devicePixelRatio
maior
que 1 pode ser considerado de DPI alto, já que isso significa que os pixels CSS
não são iguais aos pixels do dispositivo e que as imagens estão sendo ampliadas.
Veja a seguir um resumo:
- Use CSS/SVG em vez de imagens raster, se possível.
- Use imagens otimizadas para telas de alta densidade por padrão.
- Use PNGs para desenhos simples e arte de pixels (por exemplo, logotipos).
- Use JPEGs compactados para imagens com várias cores (por exemplo, fotos).
- Sempre defina tamanhos explícitos (usando CSS ou HTML) em todos os elementos de imagem.
Desenhos simples e pixel art
Muitas vezes, as imagens pequenas podem ser evitadas usando recursos CSS ou SVG.
Não é necessário usar imagens para cantos arredondados, por exemplo, já que
a propriedade CSS border-radius
tem suporte amplo. Da mesma forma, as fontes
personalizadas têm suporte amplo, então não é recomendável usar texto "imagem".
No entanto, em alguns casos, como em logotipos, uma imagem pode ser a única solução. Por exemplo, este logotipo do Chrome tem um tamanho natural de 256 x 256. Em uma tela Retina, é possível ver o aliasing de linha em diagonais e curvas, que parece irregular e ruim, especialmente quando comparado ao texto renderizado com nitidez:


Dimensões naturais: 256x256px
, tamanho do recurso: 31 kB
, formato: PNG
Convencido? Certo? Agora vamos usar uma imagem de alta densidade. Você pode querer economizar espaço armazenando seu logotipo como um JPEG, mas isso não é uma boa ideia, já que salvar logotipos e outros gráficos em um formato com perda tende a introduzir artefatos. Nesse caso, exagerei o problema usando uma compressão muito alta, mas observe as faixas nos gradientes, as manchas em segundo plano branco e as linhas bagunçadas:


Dimensões naturais: 512x512px
, tamanho do recurso: 13 kB
, formato: JPEG
Para imagens relativamente pequenas, use PNGs 2x. A diferença de tamanho entre um PNG 1x e 2x geralmente é bastante alta (52 kB, neste caso). No entanto, no caso de um logotipo, ele é a identidade do seu site e a primeira coisa que os visitantes vão notar. Se você economizar demais na qualidade em troca do tamanho, isso será a última coisa que seus visitantes vão notar.
Confira o logotipo do Chrome em toda a sua glória, reduzido à metade das dimensões naturais para telas 2x:


Dimensões naturais: 512x512px
, tamanho do recurso: 83 kB
, formato: PNG
A marcação para renderizar a imagem acima é a seguinte:
<img src="chrome2x.png" style="width: 256px; height: 256px;"/>
Observe que especifiquei uma largura e uma altura na imagem. Isso é necessário porque o tamanho natural da imagem é de 512 px. Isso também é bom para a performance porque o mecanismo de renderização tem uma boa compreensão do tamanho do elemento e não precisa trabalhar muito para calculá-lo.
Uma possível otimização que pode funcionar é reduzir o PNG de 24 bits para um de 8 bits com paleta. Isso funciona para imagens com um pequeno número de cores, incluindo o logotipo do Chrome. Para fazer essa otimização, use uma ferramenta como http://pngquant.org/. Você pode notar um pouco de faixas aqui, mas esse arquivo tem apenas 13 kB, o que é uma economia de tamanho de 6x em comparação com o PNG original de 512x512.


Dimensões naturais: 512x512px
, tamanho do recurso: 13 kB
, formato: PNG,
8-bit palette
Imagens com várias cores
Escrevi um artigo no HTML5Rocks analisando várias técnicas de imagem responsiva e fiz pesquisas sobre a compactação de JPEG 1x e 2x e a comparação dos tamanhos e da qualidade visual resultantes. Confira um exemplo de bloco do artigo acima:

Eu rotulei as imagens com o nível de compactação (indicado pela qualidade JPEG), o tamanho (em bytes) e minha opinião subjetiva sobre a fidelidade visual comparativa (classificada por números). O interessante aqui é que a imagem 2x altamente compactada (identificada como 3) é menor em tamanho e tem uma aparência melhor do que a imagem 1x não compactada (identificada como 4). Em outras palavras, entre as imagens 4 e 3, conseguimos melhorar a qualidade da imagem duplicando cada dimensão e aumentando significativamente a compactação, ao mesmo tempo em que reduzimos o tamanho em 2 kB.
Compactação, dimensões e qualidade visual
Queria ter mais informações sobre as compensações entre o nível de compactação, as dimensões da imagem, a qualidade visual e o tamanho da imagem. Realizei um estudo com a seguinte hipótese com base no estudo acima:
Hipótese
Com compressão suficiente, uma imagem 2x vai parecer equivalente à mesma imagem no tamanho 1x com outra compressão (menor). No entanto, nesse caso, a imagem altamente compactada 2x será menor que a imagem 1x.
Processo
- Dada uma imagem de 2x, gere a de 1x.
- Comprima as duas imagens em vários níveis.
- Crie uma página de teste que mostre os dois conjuntos de imagens lado a lado.
- Encontre o lugar nos dois conjuntos em que as imagens são equivalentes.
- Observe os tamanhos de imagem e níveis de compactação equivalentes.
- Teste em telas de 1x e 2x.
Eu criei um app de comparação de imagens lado a lado semelhante à visualização de comparação do Lightroom. A intenção é mostrar imagens de 1x e 2x lado a lado, mas também permitir que você faça zoom em qualquer seção da imagem para ter mais detalhes. Você também pode selecionar entre os formatos JPEG e WebP e mudar a qualidade da compactação para conferir comparações de tamanho de arquivo e qualidade da imagem. A ideia é ajustar as configurações em várias imagens, descobrir qual qualidade de compactação, dimensionamento e formato em comparação com a qualidade da imagem com que você se sente confortável e usar essa configuração para todas as imagens.

A ferramenta está disponível para você brincar. É possível ampliar a imagem selecionando uma subárea.
Análise
A qualidade da imagem é algo subjetivo. Além disso, seu caso de uso específico provavelmente vai determinar onde suas prioridades estão no espectro de fidelidade visual e tamanho do arquivo. Além disso, diferentes tipos de recursos de imagem reagem de maneira diferente à qualidade de dimensionamento e compressão. Portanto, uma solução única pode não funcionar aqui. O objetivo da ferramenta é ajudar você a desenvolver uma intuição sobre compressões, escalas e formatos de qualidade de imagem.
Ao brincar com o zoom de imagem, algumas coisas rapidamente ficaram aparentes
para mim. Primeiro, prefiro imagens quality=30 dpr=2x
em vez de quality=90
dpr=1x
porque elas têm mais detalhes. Essas imagens também são comparáveis
em tamanho de arquivo (no caso do avião, a imagem compactada 2x é de 76
KB, enquanto a não compactada 1x é de 80 KB).
As exceções a essa regra são imagens altamente compactadas (quality<30
) com
gradientes. Elas tendem a sofrer de faixas de cores, o que é igualmente ruim
independente da escala da imagem. As amostras de pássaros e carros encontradas na ferramenta
são exemplos disso.
As imagens WebP são muito mais limpas do que as JPEG, especialmente em níveis de compactação baixos. Essa faixa de cores parece ser muito menor. Por fim, as imagens WebP são muito mais compactas.
Advertências e conclusão
Fazer com que as imagens fiquem bonitas em telas de alta densidade é apenas metade dos problemas relacionados à imagem causados por uma grande variação nas telas. Em alguns casos, talvez seja necessário veicular imagens totalmente diferentes, dependendo do tamanho da janela de visualização. Por exemplo, a foto de perfil de Obama pode ser adequada para uma tela do tamanho de um smartphone, mas o estande na frente dele e a bandeira atrás dele podem ser mais adequados para uma tela de laptop.
Eu evitei deliberadamente este tópico de "direção de arte" para me concentrar apenas em imagens de alta
DPI. Esse problema pode ser resolvido com várias abordagens
diferentes: usando consultas de mídia e imagens de plano de fundo, via JavaScript,
alguns novos recursos, como image-set
, ou no servidor. Este tópico é
abordado em Imagens de DPI alto para densidades de pixels variáveis.
Vou encerrar com alguns problemas em aberto:
- Efeitos da alta compactação na performance. Quais são as penalidades da decodificação de imagens altamente compactadas?
- Quais são as penalidades de desempenho ao redimensionar a imagem quando uma imagem de 2x é carregada em uma tela de 1x?
Em resumo, use CSS e SVG em vez de imagens rasterizadas. Se imagens raster forem estritamente necessárias, use PNGs para imagens com uma paleta limitada e muitas cores sólidas e use JPEGs para imagens com muitas cores e gradientes. A vantagem dessa abordagem é que sua marcação é praticamente inalterada. Tudo o que o desenvolvedor da Web precisa fazer é gerar recursos 2x e dimensionar as imagens corretamente no DOM.
Para mais informações, confira o artigo de Scott Jehl sobre um tema semelhante. Que suas imagens fiquem nítidas e o uso de dados da rede celular seja baixo.