Les écrans à haute densité de pixels deviennent rapidement la norme. Les créateurs de contenu doivent s'adapter à cette réalité. Voici un bref guide sur la diffusion d'images de haute qualité sur le Web aujourd'hui, sans polyfills, JavaScript, hacks CSS et fonctionnalités de navigateur qui ne sont pas encore implémentées. En un mot: sans modifier radicalement votre workflow.
Il existe aujourd'hui de nombreuses propositions d'images responsives, dont beaucoup impliquent des modifications importantes pour le développeur Web. L'attribut <img>
srcset
de la norme est difficile à implémenter, en particulier avec la complexité de la sélection supplémentaire basée sur la vue d'ensemble de srcset
:
banner-HD.jpeg 2x, banner-phone.jpeg 100w, banner-phone-HD.jpeg 100w 2x
Même si la propriété CSS image-set
n'utilise que devicePixelRatio
pour décider de l'image à charger, elle oblige toujours les développeurs à écrire beaucoup de balisage supplémentaire pour chaque image.
D'autres propositions, comme l'élément <picture>
, sont encore plus longues.
De plus, ils ne sont pas conformes aux normes. Leur disponibilité universelle est donc encore plus éloignée que l'attribut srcset. JavaScript et les solutions côté serveur sont les seules autres alternatives, mais ces approches ont leurs propres inconvénients, comme indiqué dans d'autres articles.
Cet article présente plusieurs utilisations d'images couramment rencontrées sur le Web et propose des solutions simples qui fonctionnent sur des écrans à densité de pixels élevée, mais aussi sur des écrans ordinaires. Pour les besoins de cette discussion, tout appareil qui indique une valeur window.devicePixelRatio
supérieure à 1 peut être considéré comme ayant une résolution DPI élevée, car cela signifie que les pixels CSS ne sont pas les mêmes que les pixels de l'appareil et que les images sont mises à l'échelle.
Voici un résumé de ces recommandations :
- Si possible, utilisez CSS/SVG plutôt que des images matricielles.
- Utilisez des images optimisées pour les écrans haute densité par défaut.
- Utilisez des fichiers PNG pour les dessins simples et l'art pixel (par exemple, les logos).
- Utilisez des fichiers JPEG compressés pour les images présentant une variété de couleurs (par exemple, des photos).
- Définissez toujours des tailles explicites (à l'aide de CSS ou de HTML) pour tous les éléments d'image.
Dessins simples et pixel art
Les petites images peuvent souvent être complètement évitées en utilisant des fonctionnalités CSS ou SVG.
Il n'est pas nécessaire d'utiliser d'images pour les angles arrondis, par exemple, car la propriété CSS border-radius
est largement compatible. De même, les polices personnalisées sont largement compatibles. Il est donc déconseillé d'utiliser du texte "image".
Toutefois, dans certains cas, comme pour les logos, une image peut être la seule solution. Par exemple, le logo Chrome a une taille naturelle de 256 x 256. Sur un écran Retina, vous pouvez voir l'aliasing des lignes dans les diagonales et les courbes, ce qui semble grossier et mauvais, en particulier par rapport au texte affiché de manière nette:


Dimensions naturelles: 256x256px
, taille de l'asset: 31 kB
, format: PNG
Vous êtes convaincu ? Très bien. Utilisons maintenant une image haute densité. Vous pourriez être tenté d'économiser de l'espace en stockant votre logo au format JPEG, mais ce n'est peut-être pas une bonne idée, car enregistrer des logos et d'autres éléments graphiques dans un format avec perte a tendance à générer des artefacts. Dans ce cas, j'ai exagéré le problème en utilisant une compression très élevée, mais notez les bandes sur les dégradés, les taches sur les arrière-plans blancs et les lignes désordonnées:


Dimensions naturelles: 512x512px
, taille de l'asset: 13 kB
, format: JPEG
Pour les images relativement petites, utilisez des PNG 2 x. Notez que la différence de taille entre un PNG 1x et un PNG 2x est généralement assez élevée (52 ko dans ce cas). Toutefois, dans le cas d'un logo, il s'agit de la vitrine de votre site Web et de la première chose que vos visiteurs verront. En lésinant trop sur la qualité au détriment de la taille, ce sera également la dernière chose que vos visiteurs verront.
Voici le logo Chrome dans toute sa splendeur, réduit de moitié pour les écrans 2 x:


Dimensions naturelles: 512x512px
, taille de l'asset: 83 kB
, format: PNG
Le balisage permettant d'obtenir le rendu ci-dessus est le suivant:
<img src="chrome2x.png" style="width: 256px; height: 256px;"/>
Notez que j'ai spécifié une largeur et une hauteur pour l'image. Cela est nécessaire, car la taille naturelle de l'image est de 512 px. Cela est également bénéfique pour les performances, car le moteur de rendu a une bonne maîtrise de la taille de l'élément et n'a pas besoin de travailler trop dur pour le calculer.
Une optimisation possible consiste à réduire le PNG 24 bits à un PNG 8 bits avec palette. Cela fonctionne pour les images comportant un petit nombre de couleurs, y compris le logo Chrome. Pour effectuer cette optimisation, vous pouvez utiliser un outil tel que http://pngquant.org/. Vous pouvez voir un peu de bandes ici, mais ce fichier ne fait que 13 ko, ce qui représente une réduction de taille de 6 fois par rapport au PNG 512 x 512 d'origine.


Dimensions naturelles: 512x512px
, taille de l'asset: 13 kB
, format: PNG,
8-bit palette
Images avec une variété de couleurs
J'ai écrit un article sur HTML5Rocks examinant un certain nombre de techniques d'image responsives. J'ai également effectué des recherches sur la compression JPEG 1x et 2x, et comparé les tailles et la qualité visuelle obtenues. Voici une telle carte de l'article ci-dessus:

J'ai indiqué le niveau de compression (indiqué par la qualité JPEG), la taille (en octets) et mon avis subjectif sur la fidélité visuelle comparative (classée par numéros) des images. L'élément intéressant ici est que l'image 2 x hautement compressée (étiquetée 3) est plus petite et plus belle que l'image 1 x non compressée (étiquetée 4). En d'autres termes, entre les images 4 et 3, nous avons réussi à améliorer la qualité de l'image en doublant chaque dimension et en augmentant considérablement la compression, tout en réduisant la taille de 2 ko.
Compression, dimensions et qualité visuelle
Je voulais en savoir plus sur les compromis entre le niveau de compression, les dimensions de l'image, la qualité visuelle et la taille de l'image. J'ai mené une étude avec l'hypothèse suivante, basée sur l'étude ci-dessus:
Hypothèse
Avec une compression suffisante, une image 2 x sera équivalente à la même image en taille 1 x avec une autre compression (inférieure). Toutefois, dans ce cas, l'image 2 x hautement compressée sera plus petite que l'image 1 x.
Processus
- À partir d'une image 2 x, générez-en une 1 x.
- Compressez les deux images à différents niveaux.
- Créez une page de test affichant les deux ensembles d'images côte à côte.
- Trouvez l'emplacement dans les deux ensembles où les images sont équivalentes.
- Notez les tailles d'image et les niveaux de compression équivalents.
- Essayez-le à la fois sur un écran 1x et 2x.
J'ai créé une application de comparaison d'images côte à côte semblable à la vue de comparaison de Lightroom. L'objectif est d'afficher côte à côte des images au format 1x et 2x, mais aussi de vous permettre de faire un zoom avant sur n'importe quelle section de l'image pour obtenir plus de détails. Vous pouvez également choisir entre les formats JPEG et WebP, et modifier la qualité de compression pour comparer la taille des fichiers et la qualité des images. L'idée est d'ajuster les paramètres sur plusieurs images, de déterminer le compromis entre la qualité de compression, la mise à l'échelle et le format par rapport à la qualité de l'image qui vous convient, et d'utiliser ce paramètre pour toutes vos images.

Vous pouvez tester l'outil. Vous pouvez faire un zoom avant sur l'image en sélectionnant une sous-zone à agrandir.
Analyse
Je tiens à préciser que la qualité d'image est une question subjective. De plus, votre cas d'utilisation particulier déterminera probablement vos priorités dans le spectre de la fidélité visuelle par rapport à la taille de fichier. De plus, les différents types de caractéristiques d'image réagissent différemment à la mise à l'échelle et à la qualité de compression. Il n'est donc pas nécessairement possible de trouver une solution universelle. L'objectif de cet outil est de vous aider à développer une intuition concernant les compressions, les échelles et les formats de qualité d'image.
En jouant avec le zoom de l'image, j'ai rapidement remarqué quelques points. Tout d'abord, je préfère les images quality=30 dpr=2x
aux images quality=90
dpr=1x
, car elles offrent plus de détails. La taille de fichier de ces images est également comparable (dans le cas de l'avion, l'image compressée 2 x est de 76 Ko, tandis que l'image non compressée 1 x est de 80 Ko).
Les images fortement compressées (quality<30
) avec des dégradés constituent des exceptions à cette règle. Ils ont tendance à présenter des bandes de couleur, ce qui est tout aussi mauvais quelle que soit l'échelle de l'image. Les exemples d'oiseau et de voiture disponibles dans l'outil en sont des exemples.
Les images WebP sont beaucoup plus nettes que les images JPEG, en particulier à des niveaux de compression faibles. Ce crénelage de couleur semble être beaucoup moins problématique. Enfin, les images WebP sont beaucoup plus compactes.
Mises en garde et fin
Obtenir un rendu correct des images sur des écrans haute densité ne représente que la moitié des problèmes liés aux images causés par une énorme variation d'écrans. Dans certains cas, vous pouvez diffuser des images complètement différentes en fonction de la taille de la fenêtre d'affichage. Par exemple, le portrait d'Obama peut être adapté à un écran de téléphone, mais le pupitre devant lui et le drapeau derrière lui, et d'autres peuvent être plus adaptés à l'écran d'un ordinateur portable.
J'ai délibérément évité ce thème "direction artistique" pour me concentrer uniquement sur les images haute résolution. Ce problème peut être résolu de plusieurs manières: à l'aide de requêtes multimédias et d'images de fond, via JavaScript, via de nouvelles fonctionnalités telles que image-set
ou sur le serveur. Ce sujet est abordé dans la section Images haute résolution pour des densités de pixels variables.
Je vais terminer avec quelques problèmes en suspens:
- Effets d'une compression élevée sur les performances. Quelles sont les pénalités associées au décodage d'images hautement compressées ?
- Quelles sont les pénalités de performances lorsque vous devez redimensionner l'image vers le bas lorsqu'une image 2 x est chargée sur un écran 1 x ?
Pour résumer, optez pour le CSS et le SVG plutôt que d'utiliser des images matricielles. Si des images matricielles sont strictement requises, utilisez des fichiers PNG pour les images dont la palette est limitée et qui comportent de nombreuses couleurs unies, et des fichiers JPEG pour les images comportant de nombreuses couleurs et dégradés. L'avantage de cette approche est que votre balisage est pratiquement inchangé. Tout ce qui est requis du développeur Web est de générer des éléments 2 x et de dimensionner correctement vos images dans le DOM.
Pour en savoir plus, consultez l'article de Scott Jehl sur un sujet similaire. Nous vous souhaitons de belles images et une consommation de données mobiles réduite.