Élément picture du HTML5 et son utilité pour les sites adaptatifs

Un nouvel élément d’intérêt pour les sites adaptatifs a été formalisé dans la version 5.1 de la norme HTML5. Il s’agit de l’élément picture et il permet de spécifier une série d’images en fonction de la résolution de l’écran mais aussi de la densité des pixels à l’écran.

Introduction

Les sites adaptatifs (responsive) sont un incontournable aujourd’hui pour livrer un contenu confortable pour l’usager que ce soit sur un écran de bureau, une tablette ou un appareil mobile. Les éléments clés pour la création de sites adaptatifs sont :

  1. Un rendu basé sur une grille flexible;
  2. Des éléments média flexibles (images, vidéos);
  3. Des requêtes média, un module qui provient de la spécification CSS3;

Le tout parfois épicé avec un peu de JavaScript.

Pour un meilleur affichage, la résolution de l’image doit être adaptée à l’écran. Une résolution trop grande consommera de la bande passante inutilement et une résolution trop faible donnera des problèmes de netteté au rendu. Avec les écrans à haute et ultra haute densité, la résolution doit être plus forte pour assurer une netteté de l’image1. Un écran à simple densité d’un petit appareil se contentera d’une faible résolution. Envoyer une résolution trop forte à un tel appareil augmentera inutilement le temps de chargement de la ressource. D’un autre point de vue, un écran à ultra haute densité pourrait vouloir une image à plus basse résolution parce que la bande passante n’est pas au rendez-vous. Comment faire pour que l’image téléchargée soit à une résolution optimale pour l’appareil?

Méthodes du passé

Dans le passé, pour pallier au problème, il fallait dynamiquement faire des changements au niveau du Document Object Model (DOM) ou sinon après avoir envoyé un cookie avec les caractéristiques de l’environnement client, laisser le serveur envoyer l’image à la bonne résolution. Le fragment de code ci-dessous montre la méthode avec le DOM. Tout d’abord nous avons le HTML :

<img src="images/cathedrale-paris.jpg" class="hr-js" />

Puis, le JavaScript avec jQuery :

$(document).ready(function(){
    if (window.devicePixelRatio > 1) {
        var lowresImages = $('img.hr-js');
        lowresImages.each(function(i) {
            var lowres = $(this).attr('src');
            var highres = lowres.replace(".", "@2x.");
            $(this).attr('src', highres);
        });
    }
});

Sur mon Macbook Pro avec un écran haute densité, window.devicePixelRatio retourne la valeur 2, le URL serait donc changé dynamiquement par le code JavaScript pour faire télécharger l’image images/cathedrale-paris@2x.jpg qui serait à haute résolution.

Il existe d’autres astuces qui vont jouer avec les CSS et les requêtes média pour cacher le contenu de l’image (celui de l’élément img) et remplacer par une image de fond à plus haute résolution. Pour ce HTML :

<div class="retina-fond">
  <img src="images/cathedrale-paris.jpg" width="640" height="480"/>
</div>

Nous pourrions mettre les règles CSS suivantes :

@media only screen and (min-device-pixel-ratio: 2) {
  .retina-fond {
    background:url(images/cathedrale-paris@2x.jpg) no-repeat center center;  
    background-size:100% 100%;
  }
  .retina-fond img {
    visibility:hidden
  }
}

Le problème avec toutes ces techniques est qu’elles sont des « astuces », et en bout de ligne on se retrouve souvent à charger 2 images : l’image à basse résolution et l’image adéquate pour les caractéristiques de l’écran de l’appareil.

Nouveautés pour les sites adaptatifs dans le HTML5.1

Le standard HTML5.1 a un nouvel élément qui permet au navigateur de demander la bonne image dans le bon contexte. Il s’agit de l’élément picture. Cet élément permet de mettre une cascade d’éléments source. L’élément source a un attribut media qui correspond à une requête média et un attribut srcset qui spécifie une liste de URL pour chaque niveau de densité de l’écran. L’attribut srcset est une liste séparée par des virgules de chemins de fichiers (URL) avec un code pour la densité de pixels. Le navigateur choisira la première option dans la liste qui est conforme avec la contrainte média.

<picture>
  <source media="(max-width: 767px)"
    srcset="images/bonhomme-br@1x.png 1x,
      images/bonhomme-br@2x.png 2x,
      images/bonhomme-br@3x.png 3x">

  <source media="(min-width: 768px) and (max-width: 991px)"
    srcset="images/bonhomme-mr@1x.png 1x,
      images/bonhomme-mr@2x.png 2x,
      images/bonhomme-mr@3x.png 3x">

  <source media="(min-width: 992px)"
    srcset="images/bonhomme-hr@1x.png 1x,
      images/bonhomme-hr@2x.png 2x,
      images/bonhomme-hr@3x.png 3x">

  <img src="images/bonhomme.png">
</picture>

Le code ci-dessus offre trois séries d’images. La première pour des petits écrans avec une largeur maximale de 767px. La deuxième est pour une largeur d’écran supérieure à 768px mais inférieure à 991px. La dernière est pour une largeur d’écran supérieure à 992px Pour chaque srcset nous avons trois possibilités de densité (simple avec 1x, haute avec 2x et ultra haute avec 3x) avec le URL qui correspond à chacune. Finalement, un dernier élément, img, permet une reprise si l’élément picture n’est pas supporté. Au total dans notre exemple nous aurions besoin de notre image à 10 résolutions.

Essayer la démo en ligne.

Figure 1 — Rendu de l’élément picture à différentes résolutions d’écran. Ici, l’image change volontairement pour montrer le traitement de la requête média. Les captures d’écran ont été faites avec un navigateur sur un ordinateur avec un écran standard (autrement dit, pas à haute densité).

Quelle est la conséquence de cette nouvelle construction? Le navigateur fera de façon native une requête pour l’image appropriée sans recours au JavaScript, ni travail de reconnaissance côté serveur. Aucune image surdimensionnée ne sera envoyée : le téléchargement sera donc optimal.

Dans la même veine de changements, le HTML5.1 a aussi introduit ce même attribut srcset pour l’élément img. Ainsi nous pouvons mettre :

<img src="images/bonhomme-br@1x.jpg" 
    srcset="images/bonhomme-br@1x.jpg 1x,
      images/bonhomme-br@2x.jpg 2x, 
      images/bonhomme-br@3x.jpg 3x">

Les conditions peuvent inclure des éléments tels que la densité de pixels ou encore la largeur et la hauteur. Cependant, seule la densité de pixels bénéficie, à ce jour, d’une vaste prise en charge.

L’élément img a aussi la possibilité d’accueillir un attribut sizes qui permet de spécifier la taille relative de l’image dans l’écran (p.ex. une image qui couvrirait la moitié de la largeur de l’écran) et en fonction de ça, le choix du fichier approprié pour l’image sera déterminé par les options dans l’attribut srcset. Pour des détails sur l’usage l’attribut sizes, consultez la section Images à dimensionnement relatif de l’article sur les images sur le blogue de Google.

Que faire si le support n’est pas disponible?

Comme l’élément picture est relativement nouveau, il est toujours de recommandé d’aller voir son support dans les navigateurs avant de l’utiliser. Un bel outil pour ceci est le site caniuse.com. À la Figure 2, nous voyons une capture du verdict de caniuse.com pour l’élément picture à la date de l’écriture de cet article. Comme nous pouvons le voir, le plus embêtant est que cet élément n’est pas supporté dans IE 11 (mais il est disponible dans Edge depuis la version 13).

Figure 2 — Support de l’élément picture sur caniuse.com le 20 septembre 2017.

Lorsque le support est absent sur certaines plates-formes nous pouvons essayer de trouver un correctif pour l’utiliser dès maintenant. En anglais, les correctifs sont appelés les polyfills. À cet effet, il existe un correctif pour l’élément picture. Mais nous pourrions décider de ne pas utiliser le correctif et plutôt de laisser l’élément img dans la construction de picture prendre le relais. Si nous testons l’exemple de code avec l’élément picture dans IE 11 sans mettre de correctif, nous voyons l’image images/bonhomme.png.

Figure 3 — Exemple du rendu de notre code avec l’élément picture dans IE 11 : le support n’est pas disponible alors c’est l’élément img qui est utilisé.

Avantage et conséquences

Cet article a présenté un petit truc qui permet d’améliorer fortement le téléchargement des pages d’un site Web adaptatif à une époque où la vitesse de téléchargement des pages est récompensée par Google, mais aussi très appréciée des internautes.

C’est certain que ceci vous demandera de faire générer une brochette d’images à toutes les résolutions nécessaires, mais c’est une opération assez commune à configurer dans tout CMS qui se respecte. Le prix à payer sera l’espace disque. Dans les cas où l’image est une forme assez simple à vectoriser, il est certain qu’il serait avantageux d’utiliser le format SVG car dans ce cas nous n’aurions besoin que d’une image unique.

Noter que si vous faites un travail plus manuel, Photoshop CC2017 a une nouvelle fonction pour produire et sauvegarder d’un coup une série d’images pour les écrans haute densité. Une capture d’écran de l’outil d’export est présentée à la Figure 4. C’est d’ailleurs comme ça que les images de l’exemple dans cet article ont été créées.

Figure 4 — Export d’une brochette d’images à différentes résolutions dans Photoshop CC2017.

Pour ceux qui veulent plus de détails sur la technique, le sujet est brièvement couvert dans le cours d’HTML5, mais le cours Responsive Web Design est celui qui est le plus indiqué car le contexte de l’usage de cet élément est couvert en profondeur.

1Les écrans haute densité sont appelés écrans Retina (Retina Displays en anglais) pour les ordinateurs de la compagnie Apple.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *


*