Images responsive avec srcset et sizes : guide pratique
Servir une image de 2 000 pixels à un mobile affichant 375 px CSS est l'une des erreurs les plus répandues sur le web. Le visiteur télécharge 5 à 10 fois plus de données que nécessaire, dégradant le LCP et consommant inutilement la bande passante mobile. Les attributs HTML srcset et sizes, ainsi que l'élément <picture>, permettent de résoudre ce problème avec élégance, sans JavaScript, sans serveur.
Le problème fondamental : une image, tous les écrans
Sans images responsives, votre HTML ressemble à ceci :
<img src="photo-1920.jpg" alt="Photo de produit">
Le navigateur télécharge systématiquement photo-1920.jpg quel que soit l'écran. Sur un iPhone 14 (375 px CSS, DPR 3), voici ce qui se passe :
- L'image s'affiche sur 375 px CSS de large
- En Retina (Device Pixel Ratio 3), le navigateur a besoin de 375 × 3 = 1 125 pixels physiques
- Vous servez 1 920 px : plus de 40 % des pixels sont téléchargés inutilement
- Sur une connexion 4G moyenne, cette image superflue retarde l'affichage de 0,5 à 1,5 secondes
Les attributs srcset et sizes permettent au navigateur de choisir lui-même la variante la plus adaptée à son contexte (taille du viewport, densité d'écran, vitesse de connexion).
L'attribut srcset : décrire les variantes disponibles
srcset liste les versions de l'image disponibles, avec leur largeur en pixels via le descripteur w :
<img
src="photo-800.webp"
srcset="photo-400.webp 400w,
photo-800.webp 800w,
photo-1200.webp 1200w,
photo-1600.webp 1600w"
alt="Photo de produit"
width="800"
height="600">
L'attribut src sert de fallback pour les navigateurs très anciens ne supportant pas srcset, un cas quasi inexistant en 2026 (couverture > 97 %).
Le descripteur x : pour les images à taille fixe
Pour des images dont la taille CSS est fixe quelle que soit la fenêtre (logo, avatar, miniature fixe), utilisez le descripteur de densité x plutôt que w :
<!-- Logo 200 px CSS fixe : servir 2x sur les écrans Retina -->
<img
src="logo-200.webp"
srcset="logo-200.webp 1x,
logo-400.webp 2x,
logo-600.webp 3x"
alt="Logo de la marque"
width="200"
height="50">
w (avec sizes) pour les images fluides dont la taille varie selon le viewport. Utilisez x pour les images à dimensions CSS fixes (logos, avatars, vignettes de taille fixe).
L'attribut sizes : indiquer la taille d'affichage prévue
Sans sizes, le navigateur doit deviner à quelle taille l'image sera affichée au moment du préchargement (avant même d'analyser le CSS). Il suppose par défaut 100 vw (pleine largeur), ce qui l'incite à télécharger une variante trop grande pour les images dans des colonnes étroites.
sizes décrit, via des media conditions, la largeur d'affichage de l'image selon la largeur du viewport :
<img
src="photo-800.webp"
srcset="photo-400.webp 400w,
photo-800.webp 800w,
photo-1200.webp 1200w"
sizes="(max-width: 600px) 100vw,
(max-width: 1024px) 50vw,
33vw"
alt="Vignette dans une grille 3 colonnes"
width="400"
height="300">
Lecture : en dessous de 600 px de viewport, l'image occupe 100 % de la largeur ; entre 600 et 1024 px, 50 % (grille 2 colonnes) ; au-delà de 1024 px, 33 % (grille 3 colonnes). Le navigateur utilise ces informations et la densité d'écran pour choisir la variante la plus économe.
sizes doit refléter exactement votre CSS de mise en page. Si votre grille passe de 1 à 2 à 3 colonnes selon les breakpoints, sizes doit utiliser exactement les mêmes breakpoints. Un outil comme RespImageLint peut auditer vos attributs sizes automatiquement.
L'élément <picture> : art direction et formats modernes
L'élément <picture> sert deux objectifs distincts :
1. Art direction : servir une composition différente selon l'écran
L'art direction consiste à servir une image différente (recadrée, recadrée sur le sujet, orientation différente) selon la taille de l'écran, pas juste une image plus petite :
<picture>
<!-- Mobile : version portrait, recadrée sur le sujet principal -->
<source
media="(max-width: 600px)"
srcset="hero-portrait-600.webp 600w,
hero-portrait-1200.webp 1200w">
<!-- Desktop : version paysage pleine largeur -->
<source
media="(min-width: 601px)"
srcset="hero-paysage-800.webp 800w,
hero-paysage-1600.webp 1600w">
<!-- Fallback obligatoire -->
<img
src="hero-paysage-800.webp"
alt="Visuel principal"
width="1600"
height="900"
fetchpriority="high">
</picture>
2. Formats modernes avec fallback gracieux
Le navigateur essaie les <source> dans l'ordre et s'arrête au premier supporté. Aucune logique côté serveur n'est nécessaire :
<picture>
<!-- AVIF pour les navigateurs récents (~93 % en 2026) -->
<source
type="image/avif"
srcset="photo-400.avif 400w,
photo-800.avif 800w,
photo-1600.avif 1600w"
sizes="(max-width: 600px) 100vw, 50vw">
<!-- WebP pour les navigateurs modernes (~97 %) -->
<source
type="image/webp"
srcset="photo-400.webp 400w,
photo-800.webp 800w,
photo-1600.webp 1600w"
sizes="(max-width: 600px) 100vw, 50vw">
<!-- JPEG : fallback universel, toujours présent -->
<img
src="photo-800.jpg"
alt="Description de la photo"
width="800"
height="600"
loading="lazy">
</picture>
<picture> doit toujours contenir un <img> comme dernier enfant. C'est lui qui porte les attributs alt, width, height, loading et fetchpriority. Les <source> ne peuvent pas exister sans lui.
Exemples concrets par type d'image
Image hero (above-the-fold, LCP)
<picture>
<source
type="image/avif"
srcset="/img/hero-800.avif 800w,
/img/hero-1440.avif 1440w,
/img/hero-1920.avif 1920w"
sizes="100vw">
<source
type="image/webp"
srcset="/img/hero-800.webp 800w,
/img/hero-1440.webp 1440w,
/img/hero-1920.webp 1920w"
sizes="100vw">
<img
src="/img/hero-1440.jpg"
alt="Bannière principale"
width="1920"
height="800"
fetchpriority="high">
<!-- PAS de loading="lazy" sur l'image LCP ! -->
</picture>
Vignette produit dans une grille e-commerce
<picture>
<source
type="image/webp"
srcset="/img/produit-300.webp 300w,
/img/produit-600.webp 600w,
/img/produit-900.webp 900w"
sizes="(max-width: 480px) 50vw,
(max-width: 1024px) 33vw,
25vw">
<img
src="/img/produit-300.jpg"
alt="Nom du produit"
width="300"
height="300"
loading="lazy">
</picture>
Avatar utilisateur (taille fixe)
<img
src="/avatars/user-48.webp"
srcset="/avatars/user-48.webp 1x,
/avatars/user-96.webp 2x"
alt="Avatar de Jean Dupont"
width="48"
height="48"
loading="lazy">
Erreurs fréquentes à éviter
- Oublier sizes avec srcset w : sans
sizes, le navigateur suppose 100 vw et télécharge systématiquement une variante trop grande pour les images dans des colonnes - Mettre loading="lazy" sur l'image LCP : c'est l'une des causes les plus fréquentes d'un mauvais score LCP
- Oublier width et height : sans dimensions, le CLS (Cumulative Layout Shift) est garanti pour toutes les images
- Des variantes aux tailles trop proches : proposer 800w, 900w et 1000w n'a aucun intérêt. Espacez les variantes d'au moins 50 % (ex. 400w, 800w, 1600w)
- Ne pas inclure le <img> dans <picture> : les
<source>sans<img>ne s'affichent pas, le fallback est obligatoire - Dupliquer sizes dans chaque <source> : dans une balise
<picture>multi-format, répétez biensizessur chaque<source>car certains navigateurs ne l'héritent pas du<img>
Support navigateur et outils
En 2026, srcset, sizes et <picture> sont supportés par plus de 97 % des navigateurs en usage actif. Les navigateurs non compatibles ignorent ces attributs et chargent l'image dans src, le fallback est automatique et fonctionnel.
Pour générer les variantes responsives, utilisez imgpact (redimensionnement par lot) ou un CDN d'images comme Cloudinary, ImageKit ou imgix qui génère les variantes à la volée via les paramètres d'URL, sans pré-générer chaque taille.
Essayez les outils imgpact
Générez toutes vos variantes responsives (400 px, 800 px, 1600 px) et convertissez-les en WebP en quelques secondes, sans installation, directement dans le navigateur.