Le gros problème du Responsive Web Design tient probablement dans la gestion des ressources chargées et utilisées sur une page web, utiles à notre terminal et adaptées à notre écran ou notre fenêtre de consultation. Stéphanie nous en parlait déjà avec Responsive Webdesign - présent et futur de l'adaptation mobile.
Je vous avais parlé l'an dernier de l'annonce du moteur WebKit (12 août 2013) concernant son support de l'attribut srcset ; c'est aujourd'hui Google qui publie la version 34.0.1847.116 (retenez 34, ça suffira) de son navigateur Chrome (qui est passé sous moteur Blink, fork récent de WebKit). Parmi les mises à jour, on retrouve les corrections de sécurité habituelles, mais également la prise en charge partielle de l'attribut srcset
pour les éléments images <img>
.
L'attribut srcset
, principes
Lorsque vous insérez une image dans votre page web, il y a de fortes chances pour que vous utilisiez un code semblable à :
<img src="mon-image.jpg" width="850" height="475" alt="">
Ce code vous permet de charger une image en réservant un espace de 850 pixels de large aussi bien sur un écran classique que sur un écran de smartphone. Avec un peu de chance vous avez un code CSS bien construit qui vous permet de redimensionner l'image pour éviter les débordement.
img {
max-width: 100%;
height: auto;
}
Mais vous conviendrez que charger une image de 850 x 475 px n'est pas très adapté sur un écran de 320 px de large (si on prend comme exemple la largeur actuelle gérée par l'iPhone). Une image de cette taille pèse environ 150 Ko (compression de 40% sur une photographie), là où une image adaptée de 320 x 179 px ferait environ 23 Ko avec la même compression. Soit une différence de 127 Ko, multiplié par le nombre d'images du même genre dans votre page.
Attribut srcset : exemple
L'attribut srcset
vient apporter une solution à ce problème en vous permettant de définir une image adaptée au terminal de consultation en ciblant la taille de l'écran, et également la densité de pixels. Voici par exemple une utilisation envisageable de l'attribut srcset
:
<img src="mon-image.jpg"
srcset="mon-image.jpg 1x,
mon-image-320.jpg 320w 1x,
mon-image-640.jpg 320w 2x"
width="850" height="475" alt="">
Dans cet exemple, une image de 850 pixels de large est chargée grâce à src
. Cela permet aux navigateurs ne prenant pas en charge l'attribut srcset
de charger une image de contenu. Les autres navigateurs vont vérifier s'ils trouvent une correspondance dans les critères de srcset
, s'ils ne trouvent rien ils chargeront l'image de base, autrement ils chargeront une image adaptée.
La syntaxe de la valeur d'attribut est la suivante :
<adresse-de-l-image> [critère( critère)](, <adresse-de-l-image> [critère( critère)])
Si le ou les critères (entre crochets) correspondent au terminal qui consulte la page web, alors l'image (entre crochet) sur la gauche du critère sera chargée.
Dans l'exemple précédent nous avons plusieurs alternatives pour chaque image :
- 1x : cas d'une densité de pixels égale à 1 (correspondant en fait à notre valeur de src ici)
- 320w 1x : cas où la largeur du viewport est inférieure ou égale à 320px (iPhone 3 par exemple)
-
320w 2x : cas où la largeur du viewport est inférieure ou égale à 320px et où la densité de pixel est inférieure ou égale à 2 (iPhone 4 par exemple)... et supérieure à 1 puisqu'il y a déjà un intervalle pour les densités inférieures ou égales à 1 dans notre
srcset
.
Une image correspondante sera chargée, et uniquement celle-ci afin d'éviter le chargement des images inutilisées.
Particularité et problèmes à prévoir
La syntaxe n'est pas forcément intuitive et ne nous dit rien sur le sens des critères attribués à chaque image.
S'agit-il d'une égalité à la valeur du critère, d'une limite haute ou d'une limite basse ? Pour comprendre le comportement attendu, il faut... lire la doc !
Valeur des critères
Celle-ci précise que "la limite haute est l'infini" – ça fait loin – "sauf si un autre critère vient remplacer cette limite haute". Ainsi, il est possible de comprendre que si je définis un critère à 320w, je définis une nouvelle limite haute pour mon image, c'est à dire que n'importe quel terminal se situant entre 1 et 320px de largeur correspondra à ce critère.
Dès lors que je cible deux limites hautes pour deux images différentes, je crée un intervalle. Par exemple :
<img src="mon-image.jpg"
srcset="mon-image-320.jpg 320w,
mon-image-640.jpg 640w"
width="850" height="475" alt="">
Ce code permettrait de définir une image de 320px de large pour un terminal dont la largeur est comprise entre 1 et 320px, puis une image de 640. (Note : à l'heure actuelle, Chrome ne reconnaît pas les valeurs de viewport, donc cet exemple précis).
Image affichée VS image(s) chargée(s) ?
L'un des intérêt de cet attribut est qu'il prenne la place de l'attribut src
si l'un des critères est validé, l'avantage étant, de ce fait, de ne charger que l'image la plus intéressant pour le terminal qui consulte votre page web. D'ailleurs le processus est détaillé sur la page du W3C.
Figurez-vous que c'est exactement ce que fait Chrome 34 (j'avais bien le droit d'en douter !), et c'est une bonne nouvelle. Il ne reste plus qu'à voir cela appliqué aux navigateurs "mobiles".
Mais comment réagit le navigateur s'il rencontre deux images dont les critères correspondent ?
Très bonne question, nous nous sommes posé la même. Pour effectuer le test, nous avons regroupé plusieurs images identiques dans leurs proportions et ajouté un mot dessus pour détecter rapidement laquelle est chargée. Puis nous avons appliqué des critères bidons et des critères correspondant à notre terminal de test (viewport 1920px, densité de 1.0).
Test N°1 : La densité
<img src="mon-image.jpg"
srcset="mon-image-big.jpg 1x,
mon-image-hd.jpg 2x"
width="850" height="475" alt="">
L'image "big" correspondant au critère "1x" est chargée, donc tout va bien.
Test N°2 : L'absent
<img src="mon-image.jpg"
srcset="mon-image-hd.jpg 2x"
width="850" height="475" alt="">
Ici aucun critère de srcset
ne correspond, l'image du src
est chargée.
Test N°3 : Le viewport
<img src="mon-image.jpg"
srcset="mon-image-320.jpg 320w,
mon-image-big.jpg 1920w"
width="850" height="475" alt="">
Là c'est la catastrophe ! Lorsqu'il y a un intervalle de Viewport, Chrome semble complètement bogué et prend systématiquement la première image qu'il rencontre. Même en plaçant un premier critère à 3000w
, Chrome chargera la première image.
Test N°4 : Les correspondances multiples
Difficile de proposer un contrôle en remplissant le critère de densité d'une part, et le critère du viewport d'autre part, puisque le second est bogué. Du coup j'ai tenté avec deux fois le même critère en attendant de pouvoir faire mieux.
<img src="mon-image.jpg"
srcset="mon-image-big.jpg 1x,
mon-image-hd.jpg 1x"
width="850" height="475" alt="">
L'image "big" est bien chargée et affichée, aucun autre chargement d'image n'est effectué.
Support et limites
Il ne s'agit donc que d'un support partiel proposé par Chrome 34. En effet le support de l'attribut semble bogué puisque dès que vous renseignez un critère en "Nw", le navigateur affiche la première image trouvée. Le support semble plutôt bon pour la densité de pixel par contre.
Attendons de voir ce que vont proposer les prochaines implémentations.
Navigateurs | Versions | Détails |
---|---|---|
![]() |
Internet Explorer | Non supporté |
![]() |
Firefox Firefox Mobile |
Non supporté |
![]() |
Chrome 34+ Chrome Mobile 34+ |
Partiellement supporté Partiellement supporté |
![]() |
Opera Opera Mobile |
Non supporté |
![]() |
Safari |
Non supporté |
![]() |
Android Browser | Non supporté |