Apprendre à optimiser vos images pour le responsive et les écrans Retina

Quentin Busuttil

Pour réagir au contenu de ce guide, un espace de dialogue vous est proposé sur le forum. Commentez

- Titre : Apprendre à optimiser vos images pour le responsive et les écrans Retina

- Auteur : Quentin Busuttil

- Parution : 26 septembre 2017

- Mise à jour : 15 mai 2018

- Licence : Le contenu de cet article est rédigé par Quentin Busuttil et est mis à disposition selon les termes de la Licence Creative Commons Attribution - Pas d'Utilisation Commerciale - Pas de Modification 3.0 non transposé. Les logos Developpez.com, en-tête, pied de page, css, et look & feel de l'article sont Copyright ® 2013 Developpez.com.

Sommaire

- I. Introduction

- II. Définition et résolution

- III. Et le rétina fut

- IV. Les formats d’images

- IV-A. Les vecteurs, parés en toute circonstance

- IV-B. Les formats bitmap

- V. Place au code

- V-A. Les images en CSS

- V-B. Les images en HTML

- V-B-1. Utilisation d’images de différentes tailles

- V-B-2. Utilisation d’images haute résolution

- V-B-3. Utilisation de différents formats

- V-B-4. Utilisation d’images différentes selon le contexte

- V-B-5. On mixe le tout

- VI. Note de la rédaction de Developpez.com

I - Introduction

La « technologie » Retina, si on peut l’appeler ainsi, consiste en une densité de pixels assez élevée pour que l’œil (d’où le nom de Retina) ne puisse discerner les pixels sur l’écran. Cependant, avec une telle densité, pour éviter que tout paraisse minuscule, la valeur en pixels de chaque élément est doublée. Concrètement, cela signifie que dans votre feuille CSS, tout élément que vous définissez, par exemple, avec une width:100px; fera en réalité 200px. Tout est multiplié par deux.

À de telles résolutions, autant dire que vos images peuvent vite paraître pour le moins pixelisées. Il faut donc penser aux différentes tailles d’écrans, mais aussi aux différentes densités d’écrans. Un 22″ HD (1920×1080) n’aura pas besoin de la même qualité d’image qu’un 22″ en 4k (4096×2016). Voyons comment penser nos images pour qu’elles soient éclatantes en toute situation.

II - Définition et résolution

Commençons par clarifier deux notions qui sont très souvent source de confusion. La définition d’une image numérique fait référence à ses dimensions en pixels, soit 1000x1000 px, 1920×1080, etc. C’est simplement le nombre de pixels en longueur fois le nombre de pixels en largeur. L’opération donne le nombre total de pixels que contient l’image.

Quant à la résolution, elle concerne la densité d’information d’une image (ou d’un écran). Ainsi, pour une taille donnée, une image peut avoir plus ou moins d’informations. On parle généralement de ppi ou ppp en français pour les images numériques et de dpi ou ppp en français pour l’impression.

Dans le cas du numérique, on compte le nombre de pixels par pouces, tandis que dans l’imprimerie, il s’agit du nombre de points (les petites gouttes d’encre) par pouce.

Ainsi, une image de 1000x1000 px à 100 dpi fera 10″x10″ (25,4 cm). Si l’on veut que la même image possède une résolution de 300 dpi, cette dernière devra être affichée sur une surface de 3,33×3,33″ (8,5 cm). Si l’on veut conserver la même taille physique d’image pour une résolution de 300 dpi, alors notre image source devra être de 3000x3000 px.

On comprend donc que la résolution est un rapport entre la définition et la dimension qu’occupe l’image. C’est pourquoi, sur les supports numériques, parler de la résolution d’une image n’a que peu de sens. Une image de 300x300 px affichée sur un écran sera affichée à la taille de 300x300 px, le ratio est donc de 1:1.

III - Et le rétina fut

Il y a une petite exception à ce que je viens de dire plus haut : les écrans à haute densité — plus communément appelés rétina. Ce type d’écran possède une densité de pixels très importante. À tel point que l’œil ne peut plus discerner les points des pixels (d’où le nom de rétina…).

Retina est une marque d’Apple, la majeure partie des fabricants proposent aujourd’hui des écrans à haute densité de pixels. Le terme rétina est utilisé dans l’usage courant de façon générique pour désigner les écrans à haute résolution.

Il n’y a pas de norme particulière permettant de définir qu’à partir d’une certaine densité de pixels par pouce, un écran est rétina ou non. À partir d’une certaine distance, tout écran devient rétina. C’est pourquoi les écrans de téléphone — que l’on regarde de près — nécessitent en général une densité plus importante que ceux des ordinateurs.

Cela a pu varier selon les époques et les constructeurs, mais traditionnellement, les écrans présentaient une résolution de 96 dpi. Ainsi, le rétina correspond à 2×96 soit une résolution de 192 dpi, mais il existe des densités bien plus importantes.

Avec ce type d’écran, si on maintenait un ratio de 1:1, tout serait tout petit. Donc pour conserver des proportions raisonnables, tout est affiché avec un ratio de 2:1 ou plus. Le résultat ? Une image de 1000x1000 px est affichée comme une image de 2000x2000 px. Ainsi, plusieurs pixels physiques de l’écran affichent le même pixel de l’image, d’où la perte visible de qualité.

Pour un résultat optimal, il faudrait fournir une image de 2000x2000 px à afficher en 1000x1000 px. Comme ça, chaque pixel de l’image correspond à un pixel de l’écran. Évidemment, pour des écrans à densité encore plus importante, il faut des images d’encore meilleure qualité.

IV - Les formats d’images

À chaque situation sa solution. Il y a d’innombrables formats d’images, entre les images vectorielles et matricielles, voyons la meilleure option pour chaque cas d’usage.

IV-A - Les vecteurs, parés en toute circonstance

Évidemment, une image vectorielle fait fi des notions de pixels. Elle est vectorielle, elle ne contient donc pas un ensemble de points à afficher, mais plutôt les coordonnées géométriques des formes qu’il faut rendre. Ainsi, elle se redimensionne à l’infini. Donc qu’il s’agisse de densité ou de taille, un seul SVG convient pour toutes les configurations.

Pour tout ce qui est logo et image créés avec des outils tels qu’Illustrator ou Inkscape, n’hésitez pas, utilisez le SVG ! C’est léger, très bien supporté par les navigateurs et ce sera toujours d’une parfaite qualité. Gardez aussi à l’esprit que les différents logiciels d’édition n’optimisent pas forcément les fichiers SVG. Avant de les mettre en ligne, je vous conseille de leur faire subir une petite cure d’amincissement.

L’inconvénient, c’est que le SVG n’est pas adapté pour les photos par exemple. Traduire un paysage ou un portrait en éléments vectoriels revient à faire un fichier extrêmement lourd ou à perdre un nombre considérable de détails. Dans ces cas-là, pas le choix, il faudra se replier sur les formats matriciels.

IV-B - Les formats bitmap

Les images raster, bitmap ou encore matricielles en français, sont celles qui contiennent les informations des pixels, par opposition aux images vectorielles. Il existe des centaines de formats. Nous ne verrons que ceux utilisables sur le web.

Vous connaissez certainement les trois formats les plus populaires et nous allons en introduire une quatrième.

gif

C’est un format lossless, la qualité reste constante, il permet la transparence (d’une couleur seulement), l’animation et fonctionne avec une palette de 256 couleurs. Il est donc à utiliser pour les images aux formes géométriques principalement. Entre le svg et le png, sauf pour les animations, il n’est aujourd’hui plus très concurrentiel.

png

Il s’agit aussi d’un format lossless et il existe en deux versions : le png8 (pour 8 bits) qui embarque une palette de 256 couleurs ; et le png24 (pour 24 bits) qui fonctionne en mode couleur directe et couvre plusieurs millions de couleurs. Étant donné qu’il est lossless, les images présentant des formes clairement définies profiteront de la netteté du png. Il aura de bons résultats en termes de compression sur des images présentant de larges zones de couleurs homogènes. De manière générale cependant, il est bien plus volumineux que le jpeg.

jpeg

C’est le seul des trois formats à être lossy. C’est-à-dire que la compression du jpeg élimine des informations de l’image. On perd des détails. De ce fait, c’est aussi le format qui fournit les fichiers les plus légers. On peut définir la qualité de compression du jpeg. Plus la qualité est basse, plus la compression sera agressive et plus on perdra en détails. Le jpeg est très adapté aux images avec de nombreux détails et du bruit. De par le fonctionnement de son algorithme de compression, on constatera rapidement une altération de la qualité au niveau des dégradés de couleurs et des formes précises (texte par exemple) dès lors que le niveau de compression est un tant soit peu élevé.

webp

Il s’agit d’un format open source créé par Google avec et sans perte, qui supporte la transparence, les animations et fonctionne en mode de couleur directe. À qualité égale, il offre une taille inférieure de 20 à 40 % au png dans son mode lossless et au jpeg dans son mode lossy. Là où le bât blesse, c’est que le support navigateur est encore très faible…

En résumé, dans la plupart des cas pour la photo, tentez le jpeg. S’il y a de gros aplats de couleur où des formes géométriques très précises qui « bavent » un peu en jpeg, tentez le png. Pour le webP, nous verrons qu’il est possible de l’utiliser en complément des autres formats dans certains cas. Il ne pourra cependant pas faire cavalier seul pour le moment.

V - Place au code

Assez discuté théorie, voyons ce que l’on peut faire concrètement !

V-A - Les images en CSS

Une partie non négligeable des images utilisées sur nos sites le sont à des fins décoratives. À cet effet, il arrive bien souvent qu’elles soient gérées par CSS via la propriété background.

1. .header {

2. // image de 768px de large

3. background-image: url('/img/meeting-s.jpg');

5. // l'image est centrée et recouvre intégralement la zone

6. background-position: center;

7. background-size: cover;

8. }

10. @media (min-width: 769px) {

11. .header {

12. // image de 992px de large

13. background-image: url('/img/meeting-m.jpg');

14. }

15. }

17. @media (min-width: 992px) {

18. .header {

19. // image de 1200px de large

20. background-image: url('/img/meeting-l.jpg');

21. }

22. }

24. @media (min-width: 1200px) {

25. .header {

26. // image de 2500px de large

27. background-image: url('/img/meeting-xl.jpg');

28. }

29. }

On a là un exemple classique d’une image de fond gérée en CSS et qui répond à différentes tailles d’écrans. On utilise par défaut une petite image puis, grâce aux media queries, en fonction des tailles d’écrans (respectivement > 768, 991 et 1200 px), on utilise une image de plus grande définition pour qu’elle corresponde à la largeur de l’écran.

Les media queries permettent également de cibler les résolutions d’écrans. C’est en outre très bien supporté par les navigateurs. Il n’y a donc plus qu’à adapter notre scénario pour qu’il utilise une image adéquate en fonction de la définition et de la résolution de notre écran !

1. .header {

2. // image de 768px de large

3. background-image: url('/img/meeting-s.jpg');

5. // l'image est centrée et recouvre intégralement la zone

6. background-position: center;

7. background-size: cover;

8. }

10. @media (min-resolution: 192dpi) {

11. .header {

12. // image 2x plus grande : 1536px de large

13. background-image: url('/img/meeting-s@2x.jpg');

14. }

15. }

17. @media (min-width: 769px) {

18. .header {

19. // image de 992px de large

20. background-image: url('/img/meeting-m.jpg');

21. }

22. }

24. @media (min-width: 769px) and (min-resolution: 192dpi) {

25. .header {

26. // image de 1984px de large

27. background-image: url('/img/meeting-m@2x.jpg');

28. }

29. }

31. @media (min-width: 992px) {

32. .header {

33. // image de 1200px de large

34. background-image: url('/img/meeting-l.jpg');

35. }

36. }

38. @media (min-width: 992px) and (min-resolution: 192dpi) {

39. .header {

40. // image de 2400px de large

41. background-image: url('/img/meeting-l@2x.jpg');

42. }

43. }

45. @media (min-width: 1200px) {

46. .header {

47. // image de 2500px de large

48. background-image: url('/img/meeting-xl.jpg');

49. }

50. }

52. @media (min-width: 1200px) and (min-resolution: 192dpi) {

53. .header {

54. // image de 5000px de large

55. background-image: url('/img/meeting-xl@2x.jpg');

56. }

57. }

Dans cet exemple, nous ne prévoyons que les écrans à densité classique et les 2x, soit 192 dpi et plus. Cependant, vous pouvez prévoir différents intermédiaires, avec notamment le 1,5x pour les écrans à 120 dpi et les 3x pour les écrans de 300 dpi et plus (les smartphones récents par exemple). Certains smartphones comme la gamme des « + » d’Apple (6+, etc.) ainsi que l’iPhone 10 ont même des résolutions de plus de 400 dpi.

Vous n’avez rien de plus à faire si le background-size est fixé à cover ou contain. En revanche, si votre arrière-plan possédait « juste la bonne taille », il faudra maintenant forcer celle-ci avec background-size pour que l’image apparaisse aux bonnes dimensions et dans la résolution supérieure. Sans quoi elle sera simplement deux fois plus grande à l’écran mais sans gain de qualité.

Cloudinary a développé un outil en ligne qui permet d’automatiser la génération des images destinées aux différents breakpoints de manière automatique. À utiliser sans modération !

V-B - Les images en HTML

Jusqu’à présent, nous ne disposions que de la balise image classique <img src="…"> pour inclure des images dans nos pages. C’était quelque peu limité. Nous utilisions alors des hacks en détectant la résolution de l’écran via JavaScript et en injectant la source de l’image a posteriori. Tout cela est révolu, car le HTML nous a finalement dotés des bons outils.

Cette nouvelle syntaxe permet de répondre à quatre besoins différents :

- servir des images responsives (différentes tailles) ;

- servir des images adaptées à la densité de l’écran ;

- servir des images dans différents formats (hello webP) ;

- servir différents types d’images selon des règles contextuelles (image recadrée sur petit écran par ex.).

Nous utiliserons respectivement les termes taille, dpi, mime et art pour les quatre besoins mentionnés ci-dessus.

Nous verrons l’introduction de deux nouvelles balises. Pour les anciens navigateurs qui ne les supportent pas, aucun problème. Il y a dans tous les cas la balise img qui servira de fallback, le reste sera ignoré. Quoi qu’il en soit, soyez rassurés, car aussi bien picture que source sont très bien supportées.

Dans les cas où les navigateurs prennent en compte les nouvelles balises et attributs, celles-ci écrasent les valeurs définies dans la src de img.

V-B-1 - Utilisation d’images de différentes tailles

Il s’agit là simplement de faire du responsive classique. Si l’écran est plus grand, on propose au navigateur une image différente.

1. <img

2. src="buzut-400.jpg" alt="Buzut AFK IRL"

3. sizes="100vw"

4. srcset="buzut-200.jpg 200w,

5. buzut-400.jpg 400w,

6. buzut-800.jpg 800w,

7. buzut-1200.jpg 1200w">

On voit que la balise img gagne quelques propriétés. Ici, sizes n’a qu’une valeur et indique que l’image devra faire 100 % de la largeur du viewport. Le navigateur peut donc choisir entre une image de 200, 400, 800 ou 1200 px de large.

<img
src="buzut-400.jpg" alt="Buzut AFK IRL"
sizes="(min-width: 640px) 60vw, 100vw"
srcset="buzut-200.jpg 200w,
buzut-400.jpg 400w,
buzut-800.jpg 800w,
buzut-1200.jpg 1200w">

Dans cet exemple, on donne au navigateur une instruction supplémentaire grâce à la media query. Si la largeur de la fenêtre du navigateur est égale ou supérieure à 640 px, l’image ne fera que 60 % de la largeur du viewport, sinon elle fera 100 %. Les images proposées sont les mêmes que dans l’exemple précédent. Le navigateur choisit celle qui lui convient le mieux.

V-B-2 - Utilisation d’images haute résolution

Step numéro deux du responsive, comme nous l’avons vu plus haut en CSS, il s’agit de définir des images pour les écrans rétina.

<img
src="buzut-1x.jpg" alt="Buzut AFK IRL"
srcset="buzut-2x.jpg 2x, buzut-3x.jpg 3x">

Ici, on propose au navigateur une image par défaut, une autre correspondant au double de la définition et enfin une troisième correspondant au triple. Selon l’écran utilisé, le navigateur choisira la plus appropriée.

V-B-3 - Utilisation de différents formats

Pour ce cas d’usage, deux nouvelles balises font leur apparition. Il s’agit de source et de picture. La première permet de spécifier différents médias accompagnés des éléments qui permettent au navigateur de décider ou non de l’utiliser. La seconde permet de regrouper les balises source et media.

<picture>
<source
srcset="buzut.webp"
type="image/webp">

<img src="buzut.jpg" alt="Buzut AFK IRL">
</picture>

V-B-4 - Utilisation d’images différentes selon le contexte

<picture>
<source
media="(min-width: 1024px)"
srcset="buzut-paysage.jpg">

<img
src="buzut-portrait.jpg" alt="Buzut AFK IRL">
</picture>

On fournit ici par défaut une image en gros plan. Si le navigateur fait au moins 1024px de large, on spécifie à ce dernier d’utiliser l’image en format panoramique.

V-B-5 - On mixe le tout

On y va maintenant franco en utilisant ensemble les quatre possibilités vues précédemment.

1. <picture>

2. <source

3. media="(min-width: 1280px)"

4. sizes="50vw"

5. srcset="buzut-paysage-200.webp 200w,

6. buzut-paysage-400.webp 400w,

7. buzut-paysage-800.webp 800w,

8. buzut-paysage-1200.webp 1200w,

9. buzut-paysage-1600.webp 1600w,

10. buzut-paysage-2000.webp 2000w"

11. type="image/webp">

12. <source

13. sizes="(min-width: 640px) 60vw, 100vw"

14. srcset="buzut-portrait-200.webp 200w,

15. buzut-portrait-400.webp 400w,

16. buzut-portrait-800.webp 800w,

17. buzut-portrait-1200.webp 1200w,

18. buzut-portrait-1600.webp 1600w,

19. buzut-portrait-2000.webp 2000w"

20. type="image/webp">

21. <source

22. media="(min-width: 1280px)"

23. sizes="50vw"

24. srcset="buzut-paysage-200.jpg 200w,

25. buzut-paysage-400.jpg 400w,

26. buzut-paysage-800.jpg 800w,

27. buzut-paysage-1200.jpg 1200w,

28. buzut-paysage-1600.jpg 1800w,

29. buzut-paysage-2000.jpg 2000w">

30. <img

31. src="buzut-portrait-400.jpg" alt="Buzut AFK IRL"

32. sizes="(min-width: 640px) 60vw, 100vw"

33. srcset="buzut-portrait-200.jpg 200w,

34. buzut-portrait-400.jpg 400w,

35. buzut-portrait-800.jpg 800w,

36. buzut-portrait-1200.jpg 1200w,

37. buzut-portrait-1600.jpg 1600w,

38. buzut-portrait-2000.jpg 2000w">

39. </picture>

On résume tout ça ? Pour les navigateurs larges d’au moins 1280 pixels, la photo ne fera que 50 % du viewport et on utilise la photo en mode panorama. Pour les navigateurs intermédiaires — entre 640 et 1279 px —, la même photo est utilisée, mais elle fera 60 % du viewport et pour les navigateurs encore plus petits, elle fera 100 %. Dans chacun des cas, on propose au navigateur de choisir parmi différentes tailles d’images.

Lorsque les largeurs des images sont précisées, on n’utilise pas les notations nx. Le navigateur peut faire les maths lui-même. Enfin, si le navigateur supporte webP, il utilisera une image dans ce format.

Voilà, nous avons fait le tour de tout ce qu’il faut savoir sur le responsive et le rétina ! Des considérations matérielles au choix de la meilleure image en HTML ou CSS en passant par les différents formats, vous devriez être incollables. Et vos sites devront être parfaits en toutes situations.

VI - Note de la rédaction de Developpez.com

Nous tenons à remercier Quentin Busuttil qui nous a aimablement autorisés à publier son tutoriel : Guide ultime des images responsives & retina ready.Nous remercions également f-leb pour la relecture orthographique.