Images responsives avec srcset et sizes : servir la bonne taille à chaque écran

Comment le navigateur choisit une variante d’image, pourquoi un attribut sizes erroné lui fait télécharger des fichiers bien plus lourds, quand utiliser picture et comment gérer tout cela dans WordPress.

Un écran, une tablette et un smartphone affichant la même image en variantes de 1600, 800 et 400 pixels de large

La même page est consultée sur des écrans de 360 pixels de large et sur des moniteurs de 2560, sur des téléphones à triple densité de pixels et sur de vieux ordinateurs portables à densité standard. Si chaque visiteur reçoit la même image, quelqu’un est pénalisé : celui qui est sur smartphone télécharge un fichier conçu pour un moniteur, avec des mégaoctets inutiles sur un réseau mobile ; celui qui a un écran haute densité, si l’image est petite, voit un résultat flou. La solution existe depuis des années et tous les navigateurs la prennent en charge : les images responsives, avec les attributs srcset et sizes.

Ce sont des attributs simples à écrire et faciles à mal écrire. sizes surtout, qui indique au navigateur quelle taille l’image aura dans la page, est souvent laissé à sa valeur par défaut ou rempli approximativement, avec pour résultat que le navigateur télécharge des images bien plus grandes que nécessaire. Dans cet article, nous voyons comment ils fonctionnent, comment le navigateur choisit, quelles sont les erreurs les plus courantes, quand utiliser l’élément picture et comment gérer tout cela dans WordPress.

srcset : les variantes disponibles

L’attribut srcset liste les versions disponibles d’une même image, chacune avec sa largeur réelle en pixels, indiquée par le suffixe w. Le navigateur n’a pas besoin de les télécharger pour connaître leur taille : il la lit dans l’attribut, et choisit laquelle télécharger.

<img src="/media/scarpa-800.webp"
	srcset="/media/scarpa-400.webp 400w,
	        /media/scarpa-800.webp 800w,
	        /media/scarpa-1200.webp 1200w,
	        /media/scarpa-1600.webp 1600w"
	sizes="(min-width: 1024px) 400px, 100vw"
	width="1600" height="1200" alt="Chaussure de trail running, vue de profil">

L’attribut src reste comme solution de repli pour les clients qui ne connaissent pas srcset, et les attributs width et height servent toujours à réserver de l’espace et à éviter les décalages de mise en page, comme l’explique l’article sur le CLS : ils indiquent les proportions, pas la taille finale.

sizes : quelle taille aura l’image

Pour choisir, le navigateur doit savoir quel espace l’image occupera dans la page. Mais quand il lit le HTML et commence à télécharger les images, il n’a pas encore calculé la mise en page : il ne sait pas si l’image prendra toute la largeur, la moitié ou un tiers. L’attribut sizes le lui dit à l’avance, avec une série de conditions sur la largeur d’écran et la taille correspondante. Dans l’exemple : sur les écrans d’au moins 1024 pixels de large, l’image occupe 400 pixels ; sinon, elle occupe toute la largeur, 100vw.

Avec cette information, le calcul est simple : le navigateur prend la taille indiquée par sizes, la multiplie par la densité de l’écran, c’est-à-dire le nombre de pixels physiques qui correspondent à un pixel CSS, et choisit la plus petite variante qui couvre le résultat.

Comment le navigateur choisit la variante : sur un écran de 390 pixels de large, avec sizes 100vw l’image occupe 390 pixels, multipliés par la densité d’écran 3, ce qui donne 1 170 pixels nécessaires ; parmi les variantes de 400, 800, 1200, 1600 et 2400 pixels, pesant de 28 à 520 kilooctets, c’est celle de 1200 qui est choisie, la plus petite qui suffit
La largeur d’écran, sizes et la densité déterminent les pixels nécessaires ; le navigateur choisit la plus petite variante qui suffit.

Le navigateur a une certaine liberté dans ce choix : il peut préférer une variante déjà en cache même si elle est plus grande, et, dans certaines conditions, il peut tenir compte de la qualité de la connexion. Mais le principe est toujours le même, et la qualité du choix dépend entièrement de l’exactitude de sizes.

L’erreur la plus coûteuse

La valeur par défaut de sizes, quand il est absent, est 100vw : le navigateur suppose que l’image occupe toute la largeur de l’écran. Pour une image hero pleine page, c’est correct ; pour une image dans une grille de produits à trois colonnes, dans une barre latérale ou une vignette, c’est faux d’un facteur trois, quatre, dix. Le navigateur télécharge d’énormes variantes pour de petits espaces, et le site paraît optimisé, parce qu’il a srcset, alors qu’il ne l’est pas.

Une grille à trois colonnes sur un écran de 1440 pixels dans laquelle chaque image occupe environ 400 pixels : avec sizes 100vw, le navigateur croit que l’image fait 1440 pixels de large et télécharge la variante de 1600, 250 kilooctets ; avec sizes indiquant 400 pixels au-dessus de 1024, il télécharge la variante de 400, 28 kilooctets ; avec douze images, la différence dépasse 2,5 mégaoctets
Dans les grilles, il faut toujours corriger la valeur par défaut de sizes.

La bonne valeur se déduit du CSS de la page : pour chaque plage de largeur d’écran, quelle est la largeur de l’image. Il n’est pas nécessaire d’avoir une précision absolue : une surestimation de quelques dizaines de pixels est sans conséquence, une erreur d’un ordre de grandeur ne l’est pas. La fonction calc() permet d’exprimer des largeurs qui dépendent des marges et des espacements, par exemple calc((100vw - 64px) / 3) pour trois colonnes avec des marges latérales.

<!-- Grille : 1 colonne sur mobile, 2 sur tablette, 3 sur ordinateur avec un conteneur maximal de 1200px -->
sizes="(min-width: 1240px) 380px,
       (min-width: 768px) calc((100vw - 64px) / 2),
       calc(100vw - 32px)"

Quelles variantes générer

Les variantes doivent être choisies en fonction des mises en page réelles du site. Pour une image qui peut occuper de 360 à 1200 pixels CSS, sur des écrans de densité allant jusqu’à 3, les tailles utiles vont d’environ 400 à 2400 pixels réels. Un pas de 30 à 50 pour cent entre une variante et la suivante est un bon compromis : des pas trop petits multiplient les fichiers sans bénéfice, des pas trop grands obligent le navigateur à télécharger des variantes bien plus grandes que nécessaire.

Au-delà d’une certaine densité, le gain visuel devient difficile à percevoir, alors que le poids continue de croître. De nombreux sites, pour cette raison, plafonnent la densité effective à 2, en ne générant pas de variantes au-delà de deux fois la taille d’affichage maximale : sur un écran de densité 3, l’image reste parfaitement nette à l’œil, avec un fichier sensiblement plus léger.

Les descripteurs de densité

Pour les images qui ont toujours la même taille, comme un logo ou une icône, il existe une forme plus simple : au lieu de largeurs, srcset liste les variantes par densité, avec le suffixe x, et sizes n’est pas nécessaire.

<img src="/media/logo-200.png"
	srcset="/media/logo-200.png 1x, /media/logo-400.png 2x"
	width="200" height="60" alt="Logo de l’entreprise">

Pour les logos et les icônes, cependant, le meilleur choix est souvent le format vectoriel SVG, qui reste net à n’importe quelle densité avec un seul fichier léger.

L’élément picture : formats et direction artistique

srcset et sizes offrent au navigateur des versions de tailles différentes d’une même image, et lui laissent le choix. L’élément picture sert quand le choix doit suivre des règles précises. Le premier cas est le format : avec plusieurs éléments source, chacun avec son propre type, le navigateur utilise le premier format qu’il prend en charge, par exemple AVIF, puis WebP, puis JPEG, comme nous l’avons vu dans l’article sur les formats WebP et AVIF. Le second est la direction artistique : sur mobile, on veut une image différente, par exemple un recadrage vertical du sujet au lieu du panorama utilisé sur ordinateur.

<picture>
	<!-- Recadrage vertical sur mobile -->
	<source media="(max-width: 767px)"
		srcset="/media/hero-verticale-600.avif 600w, /media/hero-verticale-900.avif 900w"
		sizes="100vw" type="image/avif">
	<!-- Panorama sur les écrans plus larges -->
	<source srcset="/media/hero-1200.avif 1200w, /media/hero-2000.avif 2000w"
		sizes="100vw" type="image/avif">
	<img src="/media/hero-1200.jpg" width="2000" height="900"
		alt="Boutique du centre-ville au coucher du soleil" fetchpriority="high">
</picture>

Avec la direction artistique, les proportions changent d’une variante à l’autre, et pour éviter les décalages de mise en page les éléments source peuvent aussi préciser width et height, pris en charge par les navigateurs modernes.

L’image LCP responsive

Pour l’image principale de la page, qui est souvent l’élément LCP, les règles générales s’appliquent : pas de chargement différé, fetchpriority="high", variantes au format moderne. Si l’image est découverte tardivement, par exemple parce que c’est un arrière-plan défini dans le CSS, un preload doit indiquer les mêmes variantes et la même règle de taille, avec les attributs imagesrcset et imagesizes, sinon le navigateur risque de télécharger une variante puis d’en utiliser une autre, comme l’explique l’article sur preload, preconnect et fetchpriority.

Comment se comporte WordPress

WordPress génère automatiquement plusieurs tailles de chaque image envoyée et, depuis la version 4.4, ajoute srcset et sizes aux images du contenu. Les tailles générées dépendent de celles enregistrées par le cœur et par le thème ; les thèmes peuvent en ajouter d’autres avec add_image_size(). Le cœur réduit aussi automatiquement les images envoyées au-dessus d’un certain seuil de taille, en conservant l’original.

Le point faible est précisément sizes. La valeur par défaut de WordPress suppose que l’image est aussi large que sa taille enregistrée ou que l’écran, si celui-ci est plus petit : correct pour les images dans le corps d’un article, souvent faux pour les grilles, les colonnes et les fiches produit. Le filtre wp_calculate_image_sizes permet de le corriger selon le contexte. Pour les images en lazy loading, depuis la version 6.7, WordPress peut utiliser la valeur auto, qui laisse au navigateur le soin de calculer la taille réelle après la mise en page : une solution efficace pour les images sous la ligne de flottaison, prise en charge par les navigateurs basés sur Chromium.

// sizes corrects pour les vignettes de la grille de produits du thème
add_filter(
	'wp_calculate_image_sizes',
	function ( $sizes, $size ) {
		if ( 'tema-griglia' === $size ) {
			return '(min-width: 1240px) 380px, (min-width: 768px) calc((100vw - 64px) / 2), calc(100vw - 32px)';
		}
		return $sizes;
	},
	10,
	2
);

Comment vérifier

La vérification la plus directe se fait dans le navigateur. Dans les DevTools, quand on sélectionne une image, la propriété currentSrc montre quelle variante a été choisie, et le panneau indique la taille à laquelle l’image est affichée et celle du fichier. Si le fichier est deux fois plus large ou plus que l’espace affiché multiplié par la densité de l’écran, sizes est probablement faux. Il vaut la peine de répéter la vérification en simulant différents écrans, car l’erreur ne touche souvent que certaines plages de largeur.

Lighthouse signale les images surdimensionnées par un avertissement dédié, en indiquant les économies possibles. Dans le panneau Réseau, en triant par taille les images d’une page de catégorie ou d’un article avec beaucoup de photos, on voit immédiatement si le poids est raisonnable par rapport à ce que voit l’utilisateur. Les pages avec beaucoup d’images, comme les catalogues de boutiques en ligne dont parle l’article sur les Core Web Vitals pour WooCommerce, sont celles où l’erreur coûte le plus.

Un exemple

Une boutique de meubles a des pages de catégorie avec 24 produits dans une grille de quatre colonnes sur ordinateur et de deux colonnes sur mobile. Le thème enregistre une taille de vignette de 800 pixels et laisse WordPress avec la valeur sizes par défaut, qui pour cette taille indique jusqu’à 800 pixels. Sur un smartphone de 390 pixels de large, avec une densité de 3, le navigateur suppose que la vignette occupe tout l’écran et cherche 1 170 pixels réels, en téléchargeant la plus grande variante disponible, alors que chaque vignette occupe environ 180 pixels CSS, soit 540 réels. Sur ordinateur, où chaque vignette occupe environ 280 pixels et où l’écran a une densité de 1, il télécharge de nouveau la variante de 800 pixels : presque trois fois ce qui est nécessaire, pour 24 images.

Avec un filtre qui décrit la grille réelle, 280 pixels sur ordinateur et la moitié de l’écran moins les marges sur mobile, et avec une variante supplémentaire de 300 pixels, la page de catégorie passe sur ordinateur de 2,1 mégaoctets d’images à environ 700 kilooctets, et sur mobile aussi le poids baisse nettement. Aucune image n’est moins nette, parce que chacune est téléchargée exactement à la résolution à laquelle elle est affichée. C’est le genre de correctif qu’on ne voit pas dans un test de la seule page d’accueil, et qui, sur un catalogue de milliers de produits avec de nombreuses visites de catégories, fait une différence sensible aussi bien pour les utilisateurs que pour le trafic du serveur.

En bref

Les images responsives permettent à chaque visiteur de télécharger la variante adaptée à son écran. srcset liste les variantes avec leur largeur, sizes indique quelle taille aura l’image dans la page, et le navigateur multiplie par la densité de l’écran et choisit la plus petite qui suffit. L’élément picture ajoute un contrôle sur les formats et la possibilité de changer le cadrage selon l’écran.

L’erreur la plus fréquente et la plus coûteuse est un sizes laissé à sa valeur par défaut pour des images qui ne prennent pas toute la largeur : le site paraît optimisé, mais télécharge des fichiers bien plus lourds que nécessaire. Le corriger d’après le CSS réel, générer des variantes adaptées aux mises en page du site et vérifier dans le navigateur quelle variante est choisie sont des correctifs simples qui, sur les pages riches en images, font économiser des mégaoctets à chaque visite.

L’ÉTAPE SUIVANTE

Commençons
par votre site.

Parlez-nous du projet, des problèmes que vous constatez et de vos objectifs. Ensemble, nous définirons une intervention sur mesure.

Demander une analyse

Vous mène au formulaire de la page Contact.

MANAGED SERVER S.R.L.info@corewebvitals.fr +39 02 5656 9681

Du lundi au vendredi · 9 h 30 – 19 h 30 (CET)

Vous préférez un formulaire en ligne ?
Contactez-nous sur managedserver.it ↗