La Cascade

Un peu de tout sur CSS, HTML, SVG et JS,traduit du web anglophone
Rechercher

Petit guide pour l'ajout d'images

par Cristian Diaz, 31 décembre 2022, html, accessibilite, article original paru le 18 décembre 2022 dans HTMHell

Ajouter une image avec HTML n'est pas si simple, quand on commence à entrer dans les détails.


Ajouter une image avec HTML c'est assez facile, n'est-ce pas ? c'est juste une simple balise, après tout...

<img src="path/to/image.jpg" />

Mais lorsque nous commencons à prendre en considération la performance, les tailles d'écran, l'accessibilité, la densité de pixels ou les préférences de l'utilisateur, on peut finir par se demander si HTML est suffisant à lui seul pour cette tâche... Et la réponse est oui ! Le HTML a de nombreuses options et il est suffisamment puissant pour gérer cette tâche. Cet article traitera de ce que nous devons considérer au moment d'ajouter une image à un site avec HTML.

Considérations de base

Attribut alt

Commençons par un élément très important : votre image a besoin d'un texte alternatif. Ça permettra aux utilisateurs de lecteurs d'écran d'identifier le contenu de l'image, mais ça les aidera également lorsque l'image ne se charge pas (peut-être parce que l'image n'est pas disponible, ou peut-être parce que l'utilisateur a un réseau lent). Sinon, ils ne sauront pas ce qu'est l'image. Cela peut être fait avec l'attribut alt.

<img
  src="path/to/image.jpg"
  alt="Un chat blanc allongé sur un canapé"
/>

Gardez à l'esprit que parfois, une image est là à des fins purement décoratives, donc la rendre visible pour les lecteurs d'écran pourrait ne pas être idéal, dans ce cas, nous pouvons utiliser un alt vide pour que les lecteurs d'écran ignorent cette image.

<img src="path/to/image.jpg" alt="" />

Que doit contenir le texte alternatif ? En général, il doit contenir une description concise de ce que contient l'image. S'il s'agit d'une image contenant des informations importantes (comme le lieu d'un événement ou une infographie complète), ces informations doivent également figurer dans le texte alternatif. Le W3C a créé un arbre de décision alt pour nous aider à décider des informations à ajouter.

Attributs de largeur et de hauteur

L'une des mesures les plus importantes des performances est le décalage cumulatif de la mise en page (Cumulative Layout Shift, CLS), qui évalue dans quelle mesure le contenu d'un site Web se déplace lorsqu'il est à l'écran. En d'autres termes, un CLS faible signifie que le contenu est assez stable et ne créera aucun problème avec l'interactivité de l'utilisateur. Pour en savoir plus sur ce concept, vous pouvez consulter cet article sur web.dev à propos de CLS.

Le chargement d'images peut créer des problèmes de décalage de mise en page et une façon de les éviter est d'utiliser les attributs width et height pour les images. Ils indiquent au navigateur la taille intrinsèque de l'image et créent le ratio d'aspect de l'image lors du chargement du site Web, ce qui réduit le décalage de mise en page qu'il peut créer. Voici à quoi cela ressemblerait dans une image.

<img
  src="path/to/image.jpg"
  alt="Un chat blanc couché sur un canapé"
  width="1200"
  height="800"
/>

Mais ce n'est pas tout ce que nous pouvons faire pour améliorer les performances de notre site Web avec une balise img !

Chargement paresseux

Nous pouvons avoir beaucoup d'images sur notre site Web, et cela peut affecter son temps de chargement. C'est là qu'intervient le concept de chargement paresseux (lazy loading). Ça signifie que l'image ne commencera à se charger que lorsqu'elle se trouvera dans la partie visible de la fenêtre d'affichage. Il fut un temps où cela se faisait avec JavaScript mais maintenant HTML nous offre un moyen de le faire facilement en utilisant l'attribut loading="lazy".

<img
  src="path/to/image.jpg"
  alt="Un chat blanc couché sur un canapé"
  width="1200"
  height="800"
  loading="lazy"
/>

Lorsque nous utilisons loading="lazy" en tandem avec les attributs height et width, nous nous assurons que le site Web dispose de suffisamment d'espace pour l'image au moment du chargement, et en même temps, nous ne chargons l'image que si l'utilisateur en a besoin, ce qui est excellent pour les performances !

N'oublions pas cependant que si un utilisateur a désactivé JavaScript, loading="lazy" ne fonctionnera pas. Nous devons donc garder à l'esprit d'autres considérations liées aux performances, mais mettons ce sujet en veilleuse pour l'instant.

N'oublions pas non plus que l'utilisation de loading="lazy" dans notre élément Largest Content Painting (nous parlerons de cette métrique plus tard) augmentera en fait notre temps de chargement. Soyons donc prudent et testons toujours cet élément pour savoir si cet attribut donne les résultats escomptés.

figure et figcaption

Parfois, nous devons ajouter des informations supplémentaires qui ne tiendraient pas dans la balise alt, comme les crédits de l'image, ou une note importante à son sujet à laquelle nous préférons que tout le monde ait accès. Nous pouvons utiliser la balise figure pour envelopper l'img, puis ajouter une légende avec la balise figcaption.

<figure>
  <img
    src="path/to/image.jpg"
    alt="Un chat blanc couché sur un canapé"
    width="1200"
    height="800"
    loading="lazy"
  />
  <figcaption>
    Les chats persans sont reconnaissables à leurs gros poils, leur
    visage rond et leur museau court
  </figcaption>
  .
</figure>

figcaption doit être un enfant direct de l'élément figure, sinon, il pourrait ne pas être reconnu par les technologies d'assistance. C'est un point que Manuel souligne dans son article divs are bad!.

Garder ces considérations à l'esprit aide beaucoup lorsque nous créons une image, mais ce n'est que la partie émergée de l'iceberg. Lorsque nous commençons à prendre en considération de multiples variables comme les tailles d'écran, les formats d'image et les préférences des utilisateurs, la balise img commence à manquer de puissance. C'est là qu'une autre balise entre en jeu pour ajouter plus de fonctionnalités !

La balise picture

Cette balise est un conteneur pour de multiples sources d'images. Selon les conditions que nous y ajoutons, le navigateur commencera à choisir le bon fichier en fonction de multiples facteurs comme la taille du viewport, le format de l'image, la densité des pixels ou les préférences de l'utilisateur. Il agit comme un emballage pour les multiples éléments de source que nous utiliserons pour déterminer la meilleure image.

Commençons par vérifier ce que nous pouvons faire avec cet élément.

Prise en charge de différents formats d'image

À côté des formats d'image .png ou .jpg, il existe de nouveaux formats d'image tels que .avif, .webp ou .apng que nous pourrions vouloir utiliser parce qu'ils ne présentent pas de perte de qualité tout en étant beaucoup moins lourds qu'un format plus courant. Cependant, les formats d'image mentionnés précédemment bénéficient d'une prise en charge plus large. Nous pouvons utiliser la balise source pour nous permettre d'utiliser des formats d'image plus optimisés en fonction du support du navigateur. Pour cela, nous pouvons utiliser l'attribut type dans l'élément source pour indiquer le format que nous devons évaluer.

<picture>
  <source srcset="path/to/image.avif" type="image/avif" />
  <source srcset="path/to/image.webp" type="image/webp" />
  <img
    src="path/to/image.jpg"
    alt="Un chat blanc couché sur un canapé"
    width="1200"
    height="800"
    loading="lazy"
  />
</picture>

Dans ce cas, il commencera à vérifier si le navigateur accepte le format .avif, et si ce n'est pas le cas (comme Safari avant la version 16), il vérifiera si le format .webp est supporté. Si ce n'est pas le cas, il affichera celui de l'élément img. Il existe de nombreux formats d'image. Si vous voulez en savoir plus, vous pouvez consulter la documentation de MDN à ce sujet.

Vous vous souvenez que j'ai mentionné que loading="lazy" pourrait ne pas être suffisant pour des raisons de performances ? Ça nous aidera à prendre en compte la compatibilité navigateur pour charger l'image optimale, créant ainsi un système très robuste pour donner à l'utilisateur la meilleure qualité d'image possible et utiliser le moins de bande passante possible. C'est le meilleur des deux mondes, et c'est possible avec seulement du HTML !

Images responsives

Nous pourrions vouloir montrer une image différente ou une partie différente d'une image en fonction de la taille du viewport. L'élément picture peut nous y aider grâce à l'attribut media, où nous pouvons utiliser une requête media pour détecter la taille du viewport et ajouter une image différente si nécessaire.

<picture>
  <source
    srcset="path/to/image-mobile.jpg"
    media="(max-width : 600px)"
  />
  <img
    src="path/to/image.jpg"
    alt="Un chat blanc couché sur un canapé"
    width="1200"
    height="800"
    loading="lazy"
  />
</picture>

Nous pouvons y utiliser n'importe quelle requête média valide. Ainsi, par exemple, orientation : portrait et orientation : landscape sont des options valides lorsque nous souhaitons afficher une image différente selon que la largeur du viewport est supérieure (ou inférieure) à sa largeur. Il existe de nombreuses possibilités que nous pouvons envisager pour donner la meilleure image à l'utilisateur.

Préférences de l'utilisateur

Maintenant, c'est très pratique pour les performances et l'expérience utilisateur, mais c'est également utile pour l'accessibilité : nous pouvons vérifier les préférences de l'utilisateur pour aider les personnes souffrant de certains handicaps.
Par exemple, certaines personnes peuvent avoir des problèmes comme des migraines et préférer utiliser le mode sombre, et une image très lumineuse pourrait déclencher une crise de migraine, donc avoir une version de votre image mieux adaptée au mode sombre serait idéal.

Ou peut-être avons-nous un gif, et quelqu'un a désactivé les animations sur son appareil. Nous pourrions vouloir montrer une image statique à la place afin que son expérience ne soit pas affectée. Comment faire ?

Comme je l'ai mentionné, nous pouvons utiliser n'importe quelle requête média valide, ce qui inclut les requêtes média qui vérifient les préférences de l'utilisateur comme prefers-color-scheme ou prefers-reduced-motion. Nous pouvons même les combiner avec des opérateurs logiques pour afficher l'image appropriée. Voyons comment cela fonctionne avec un exemple.

<picture>
  <!-- La préférence pour le mode sombre et les animations sont désactivées -->
  <source
    srcset="path/to/image-dm.jpg"
    media="(prefers-reduced-motion : reduce) and (prefers-color-scheme : dark)"
  />
  <!-- Image statique lorsque les animations sont désactivées -->
  <source
    srcset="path/to/image.jpg"
    media="(prefers-reduced-motion : reduce)"
  />
  <!-- La préférence pour le mode sombre est vérifiée -->
  <source
    srcset="path/to/image-dm.gif"
    media="(prefers-color-scheme : dark)"
  />

  <!-- Aucune de ces préférences n'est active -->
  <img
    src="path/to/image.gif"
    alt="Un chat qui danse"
    width="1200"
    height="800"
    loading="lazy"
  />
</picture>

Il est important de noter ici que l'ordre a de l'importance. Il est préférable d'ajouter d'abord les balises ayant des exigences plus spécifiques en matière de requête média pour être sûr qu'elles ne seront pas écrasées par celles qui apparaîtront plus tard. Gardez également à l'esprit que vous pouvez combiner tout ce que vous avez vu, il y a donc beaucoup de possibilités avec les éléments picture et source.

Cela couvre pratiquement tout ce que vous devez prendre en considération, mais il y a encore quelques points que vous pouvez prendre en compte.

Considérations supplémentaires

Densité des pixels et srcset

L'attribut srcset que nous utilisons dans l'élément picture a une syntaxe légèrement différente si nous souhaitons donner une meilleure image en fonction de la densité de pixels de l'appareil. Pour cela, nous pouvons ajouter une liste d'images séparées par des virgules et après l'URL de l'image, nous mettrons le type de densité de pixels que nous voulons prendre en charge avec cette image. Voyons cela avec un exemple :

<picture>
  <source
    srcset="
      path/to/image-mobile.jpg    1x,
      path/to/image-mobile-2x.jpg 2x,
      path/to-image-mobile-3x.jpg 3x
    "
    media="(max-width : 600px)"
  />
  <img
    src="path/to/image.jpg"
    alt="Un chat blanc couché sur un canapé"
    width="1200"
    height="800"
    srcset="path/to/image-2x.jpg 2x, path/to/image-3x.jpg 3x"
    loading="lazy"
  />
</picture>

Il y a encore quelque chose que je n'ai pas mentionné et c'est le fait que nous pouvons utiliser l'attribut srcset dans l'élément img, et cela fonctionne très bien lorsque nous voulons prendre en charge des images en fonction de la densité de pixels de l'appareil. La prochaine fois que vous voudrez apporter des images de meilleure qualité pour les images en fonction de l'appareil, vous savez maintenant comment faire !

Précharger l'image pour améliorer le LCP

Vous vous souvenez quand j'ai mentionné LCP ? Il existe une autre métrique appelée Largest Content Paint (LCP) qui mesure le temps nécessaire pour charger la plus grande image (ou bloc de texte) à rendre dans le viewport. Généralement, ce LCP est une grande image. Nous pouvons utiliser d'autres formats d'image pour diminuer la taille du LCP, mais que faire si cela ne suffit pas ? Nous avons l'alternative de précharger l'image dans le head, ce qui rendra l'image plus rapide, et par extension, améliorera cette métrique. Voici à quoi cela ressemblerait dans notre balise head.

<head>
  <link rel="preload" href="path/to/image.jpg" as="image" />
</head>

Atention à ne pas abuser de cette technique cependant, car sinon, elle augmentera le temps de chargement de la page. Utilisez-la simplement pour votre ou vos images les plus importantes et testez les performances en conséquence pour vérifier si elle améliore ces métriques.

`décodage="async"``

J'ai déjà mentionné loading="lazy", mais il existe un autre attribut HTML que nous pouvons utiliser pour optimiser le temps de chargement d'un site Web. Alors que loading="lazy" décide du moment où l'image sera chargée (au moment où elle est proche du viewport), nous avons un autre attribut qui définit comment elle sera chargée.

Normalement, tout notre site sera chargé de manière synchrone parce que le navigateur lit le HTML ligne par ligne, donc s'il trouve une grande image, le reste du site ne se téléchargera pas avant que l'image soit chargée. C'est là que decoding="async" entre en jeu pour donner une indication au navigateur d'essayer de télécharger l'image et en même temps de télécharger une autre partie du site.

<img
  alt="Un chat blanc allongé sur un canapé"
  width="1200"
  height="800"
  loading="lazy"
  decoding="async"
/>

L'utilisation des deux, decoding="async" et loading="lazy", dans une image contribuera à réduire considérablement le temps de chargement d'un site Web, et le decoding est un attribut largement pris en charge.

Conclusion

Ajouter une image à un site Web est facile... Mais les choses commencent à se compliquer lorsque nous commençons à prendre en compte les considérations de performance et d'accessibilité. Heureusement pour nous, HTML peut nous donner les outils appropriés pour aborder ces considérations sans aucun problème.

J'ai choisi ce sujet pour ce calendrier de l'Avent pour une bonne raison et c'est parce qu'il m'a fait remarquer à quel point le HTML est puissant, robuste et étonnamment complexe. Voir ce que le HTML a à offrir juste pour amener la bonne image sur votre écran avec un effort relativement faible était fascinant et cela m'a donné envie de creuser plus profondément dans ce que le HTML peut faire.

Autres ressources externes

Articles de Cristian Diaz traduits dans La Cascade

Voir la page de Cristian Diaz et la liste de ses articles dans La Cascade.
Article original paru le 18 décembre 2022 dans HTMHell
Traduit avec l'aimable autorisation de HTMHell et de Cristian Diaz.
Copyright HTMHell © 2022