Optimiser les images sur le web : checklist des bonnes pratiques
lundi 24 juillet 2023
Dans les articles prĂ©cĂ©dents, je vous parlais de pourquoi il est important dâoptimiser la performance de ses pages web. Notamment, mesurer le Largest Contentful Paint (LCP) est un bon moyen de mesurer Ă partir de quand vos utilisateurices ont lâimpression que votre page est chargĂ©e.
Pour améliorer ce LCP, nous avons vu que bien maßtriser son réseau était important. De plus, en commençant à peine à effleurer le sujet des images avec des histoires de Lazyload et de Preload, nous avons gagné 20% (!) sur le LCP. Les images sont donc essentielles quand on parle de performance.
Dans cet article, nous allons continuer à améliorer celles-ci en approfondissant la gestion des images et notamment le comportement des balises <picture>
, <source>
et <img>
. A la fin, vous en sortirez avec une méthode pour choisir les bons formats et les bonnes tailles en toute circonstance.
Si vous ressentez le besoin dâavoir plus dâaccompagnement dans votre entreprise pour mettre en place ces sujets, nâhĂ©sitez pas Ă me contacter par mail. Peut-ĂȘtre pouvons nous travailler ensemble afin de poser les premiĂšres briquesâŻ?
- Pourquoi améliorer le LCP de vos pages�
- Analyser le comportement réseau pour améliorer FCP et LCP
- Optimiser la taille des images : sâen sortir avec picture, source & srcset (vous ĂȘtes ici)
- Optimiser le chargement des fonts
- Optimiser la gestion des icĂŽnes
- Comment diagnostiquer et corriger du Cumulative Layout Shift (CLS)�
- Quelles techniques pour diminuer la quantité de JavaScript� (bientÎt)
- Quelles métriques suivre en dehors des Core Web Vitals� (bientÎt)
- Et plus encore đ«¶
Rappels sur lâoptimisation rĂ©seau
Afin de commencer à rentrer dans le dur du sujet, rappelons déjà les premiÚres optimisations que vous pouvez faire à moindre coût :
GĂ©nĂ©ralement, vos images seront du jpg et/ou du png. Une image bien optimisĂ©e peut faire toute la diffĂ©rence en termes de poids de fichier (jusquâĂ -80%).
Passez donc vos images dans Squoosh avant de les afficher sur vos pages.
Toutefois, la tentation est grande de sacrifier la qualitĂ© des images pour diminuer encore plus son poids. Est-ce que ces kilo octets valent toujours le coupâŻ? Pour certain·e·s, oui. Pour dâautres, non. Câest pour cette raison que Squoosh est un bon outil : il vous permettra de choisir le niveau de qualitĂ© pertinent pour vous.
En ayant beaucoup dâimages dans votre site, vous pouvez saturer la bande passante de vos utilisateurices. Pour Ă©viter cela, toutes les images qui ne sont pas directement visibles au chargement de la page (= sans avoir besoin de scroll), doivent ĂȘtre marquĂ©es comme lazy
.
<img
alt="Le plus choupichou des choupichats"
src="cat.jpg"
width="150"
height="150"
+ loading="lazy"
>
Selon votre parc utilisateur, ce nâest peut ĂȘtre pas encore parfaitement supportĂ©. Mais nous en sommes quand mĂȘme Ă 93% du web Ă date dâĂ©criture de cet article.
Dans votre trace rĂ©seau, vous aurez peut-ĂȘtre des ressources qui passeront devant votre image principale. Afin dâĂ©viter cela vous pouvez utiliser une balise <link>
dans votre <head>
afin dâaider le navigateur Ă mieux comprendre vos prioritĂ©s.
<link rel="preload" as="image" type="image/jpeg" href="/images/banner.jpg" fetchpriority="high" />
Utiliser <picture>
pour télécharger la bonne image en fonction du navigateur
Les optimisations ci-dessus reposent sur le principe quâune seule image est disponible. Cependant, ce qui fait la beautĂ© du web, câest quâil est accessible partout, sous plein de formes diffĂ©rentes : de la montre connectĂ©e, en passant par le tĂ©lĂ©phone, jusquâĂ lâĂ©cran TV. Chaque Ă©cran aura son format, sa rĂ©solution, ses contraintes.
Prenons lâexemple de cette image en bas de page sur notre site dâexemple :

La partie visible de lâimage sur mobile est beaucoup plus resserrĂ©e en hauteur que sur desktop. Il est donc dommage dâenvoyer lâimage desktop sur mobile ou inversement. Câest dâautant plus vrai que je nâai pris que 2 screenshots. Mais si on rĂ©cupĂšre toutes les tailles, on obtient ce graphique :

đĄ Manuellement, il est laborieux de rĂ©cupĂ©rer ces courbes. Je vous conseille de passer par ce Snippet que vous pouvez exĂ©cuter directement dans la console de votre navigateur.
https://gist.github.com/JulienPradet/abfbff6577ecebd3d1ffe72f6063b1f7
En suivant les instructions de celui-ci, vous pourrez rĂ©cupĂ©rer dans votre presse-papiers la largeur et la hauteur de votre image en fonction de la taille de lâĂ©cran. Il ne vous restera plus quâĂ coller ça dans une feuille de calcul (Google Sheets/Excel/Libre Calc) pour en gĂ©nĂ©rer un graphique.
Dans notre exemple, on se rend compte quâau minimum lâimage fait 256x208 et au maximum 532x208. Pour donner une Ă©chelle de comparaison, câest du simple au double. Si lâimage avait grandit verticalement, lâordre de grandeur aurait Ă©tĂ© multiplĂ© dâautant.
Avec toutes ces informations, comment on sâen sort pour livrer la bonne image au bon navigateurâŻ?
Méthode pour choisir les bonnes images
1. Définir les breakpoints
La premiĂšre Ă©tape est de connaĂźtre votre breakpoints : quelles sont les tailles dâĂ©cran pour lesquelles vous allez choisir de charger une image diffĂ©renteâŻ? Cela va dĂ©pendre de vos media queries en CSS et de vos utilisateurices.
Dans le CSS de notre page dâexemple, nous avons :
- 600
- 1000
On les voit bien au niveau du graphe parce que cela correspond aux cassures sur les courbes. Cela dit, dans nos calculs dâimages, nous nâallons pas les prendre tels quels, mais leur soustraire un pixel (599 et 999). En effet, câest Ă ces valeurs-lĂ que les images sont gĂ©nĂ©ralement plus grandes.
Ensuite, vos utilisateurices auront certainement des rĂ©solutions diffĂ©rentes. Notamment 375px de largeur est un format encore trĂšs rĂ©pandu aujourdâhui pour les iPhones. Les tablettes sont environ vers 768px. Et sur ordinateur, on a lâhabitude du 1920x1080. Câest vrai chez les devs, mais chez beaucoup de gens, les Ă©crans de laptops sont par dĂ©faut zoomĂ©s Ă 150%, donc câest plutĂŽt du 1280x720.
đĄ Il est difficile dâavoir des ressources fiables Ă ce sujet. Il est donc vivement conseillĂ© de sortir ces donnĂ©es de vos analytics. Mais Ă dĂ©faut, nâhĂ©sitez pas Ă suivre Andy Bell (@andy@bell.bz) qui a fait une Ă©tude rĂ©cente Ă ce sujet et publiera plus dâinformations bientĂŽt.
Mise Ă jour : lâĂ©tude a Ă©tĂ© rĂ©sumĂ©e ici : https://viewports.fyi/
Pour notre exemple, nous allons donc considérer les tailles suivantes et les récupérer de notre graphe :
- 375
- 599
- 768
- 999
- 1280
- 1920

Enfin, avant de passer Ă la prochaine Ă©tape, on constate quâon peut simplifier le nombre de breakpoints parce que certains partagent des tailles dâimages trĂšs similaires. Câest le cas par exemple de 1280 & 1920 : les images font toujours 336 x 260.
Par ailleurs, si on regarde entre 375 et 399, lâimage grandit assez fortement et a un ratio trĂšs diffĂ©rent. Il est sĂ»rement pertinent de couper la poire en deux et dire que la petite image utilisĂ©e sur une largeur de 375 le sera aussi pour des Ă©crans lĂ©gĂšrement plus grands.
Si on récapitule, nous devons donc générer le tableau suivant :
Device Width | Media Query |
---|---|
375 | (max-width: 415px) |
599 | (min-width: 416px) and (max-width: 599px) |
999 | (min-width: 600px) and (max-width: 999px) |
1280 | (min-width: 1000px) |
Petit point au sujet des media queries
Dans le tableau ci-dessus, je vous ai Ă©crit les media queries de maniĂšre exhaustive. Dans les faits, le navigateur utilisera toujours la premiĂšre source compatible. Donc on peut simplifier lĂ©gĂšrement lâĂ©criture en ne passant que par des min-width (Mobile First) et en inversant lâordre du tableau.
Device Width | Media Query |
---|---|
1280 | (min-width: 1000px) |
999 | (min-width: 600px) |
599 | (min-width: 416px) |
375 |
La derniĂšre ligne nâa pas de media query parce que ce sera celle utilisĂ©e par dĂ©faut.
đĄ Que faire pour les images plein Ă©cranâŻ?
Lâexemple que nous avons pris est pour une image qui a une largeur relativement stable et fixe sur tous les Ă©crans. Si je veux rajouter une banniĂšre tout en haut de mon site, comment faireâŻ?
Il faut suivre exactement la mĂȘme mĂ©thode. La seule rĂ©elle diffĂ©rence est que vous ne pouvez pas beaucoup simplifier vos breakpoints (lâimage de 1280 ne sera pas du tout la mĂȘme que lâimage de 1920). Il y aura donc plus de lignes dans votre tableau.
2. DĂ©finir les tailles dâimages pour chaque breakpoints
Maintenant que nous savons quelles tailles dâĂ©cran regarder, nous pouvons aller rĂ©cupĂ©rer les tailles dâimages :
Device Width | Media Query | Image Size |
---|---|---|
1280 | (min-width: 1000px) | 336 x 240 |
999 | (min-width: 600px) | 240 x 300 |
599 | (min-width: 416px) | 535 x 208 |
375 | 311 x 208 |
Cela dit, ce nâest pas tout Ă fait fini. En effet, jusquâĂ maintenant on a parlĂ© de pixels. Mais ce ne sont pas de vrais pixels, ce sont des pixels CSS : 1 pixel CSS peut valoir 1, 2 ou 3 pixels physiques selon votre appareil. Par exemple, la plupart des tĂ©lĂ©phones en ont minimum 2. Les derniers iPhones en ont 3. Vous pouvez utiliser window.devicePixelRatio
pour connaĂźtre cette valeur.
Câest important parce que cela veut dire que selon lâĂ©cran physique utilisĂ© par lâutilisateurice, une image de la bonne taille (ex : 311 x 208 sur un Ă©cran de 375px) pourra paraĂźtre flou. Pour quâelle soit de bonne qualitĂ© sur un tĂ©lĂ©phone qui a un window.devicePixelRatio
de 2, il faudra plutĂŽt fournir une image de 622 x 416.
Nous allons appliquer les rÚgles suivantes pour avoir la totalité de nos images :
- si width < 1000, mettre Ă disposition des images 2x
- inutile de mettre Ă disposition des images 1x parce que tous les tĂ©lĂ©phones et tablettes aujourdâhui ont au moins un ratio de 2
- inutile de mettre un ratio de 3x parce quâil est illusoire de penser que lâĆil humain puisse distinguer ce niveau de dĂ©tail (-33% de temps de chargement chez Twitter).
- si width > 1000, mettre Ă disposition des images 1x ET 2x
- beaucoup dâĂ©crans de PC sont encore Ă une densitĂ© standard
- mais les écrans à haute densité existent aussi (par exemple les écrans 4k)
đĄ A nouveau, nâhĂ©sitez pas Ă adapter ces rĂšgles Ă la population qui visite votre site.
Device Width | Media Query | CSS Image Size | Pixel Ratio | Physical Image Size |
---|---|---|---|---|
> 1000 | (min-width: 1000px) | 336 x 240 | 1x | 336 x 240 |
2x | 672 x 480 | |||
<= 999 | (min-width: 600px) | 240 x 300 | 2x | 480 x 600 |
<= 599 | (min-width: 416px) | 535 x 208 | 2x | 1070 x 416 |
<= 375 | 311 x 208 | 2x | 622 x 416 |
Ca fait beaucoup de travail tout ça. Est-ce quâil nây a pas moyen de tricher et dâautomatiser tout çaâŻ? Ca dĂ©pend.
- Si votre image est critique / visible dĂšs le chargement de la page, alors non, il nây a pas de solution miracle si vous souhaitez conserver de bonnes performances. Certains outils peuvent vous mĂącher le travail (ex: Daltons), mais globalement il vous faudra quand mĂȘme gĂ©nĂ©rer le HTML manuellement et comprendre quelles tailles mettre Ă disposition dans vos sources.
- Si votre image est non critique, vous pouvez vous reposer sur JavaScript. En effet, en JS vous pouvez rĂ©cupĂ©rer la taille nĂ©cessaire de votre image et du coup changer lâURL de votre image Ă la volĂ©e pour utiliser la bonne taille. Câest ce que propose par exemple TwicPics (rĂ©cemment rachetĂ© par Frontify). Le seul inconvĂ©nient est que cela va potentiellement gĂ©nĂ©rer une myriade dâimages et donc vous bĂ©nĂ©ficierez moins des gains liĂ©s au cache CDNs. Mais pour des images lazyloadĂ©es câest tout Ă fait envisageable.
đĄ Pourquoi ne peut-on pas utiliser de JavaScript pour les images critiquesâŻ?
Parce que, qui dit JavaScript, dit exĂ©cution beaucoup plus tard dans le processus de chargement de votre page. Donc vous perdrez de nombreuses centaines de millisecondes sur votre LCP. Sur les quelques tests que jâai fait sur un site e-commerce en React, cela reprĂ©sentait une perte de sĂšche de 40% du LCP.
En tout cas, dans ce guide, on a fait le plus dur : on a rĂ©ussi Ă trouver les diffĂ©rentes images Ă utiliser en fonction du device. Passons au codeâŻ!
3. Générer les nouvelles images
Pour gĂ©nĂ©rer ces diffĂ©rentes tailles dâimages, vous avez 2 options :
- soit vous mettez en place une CLI ou votre propre API qui vous permet de gĂ©nĂ©rer les diffĂ©rentes tailles dâimages (sharp Ă©tant de trĂšs loin la meilleure librairie pour faire ça dans lâĂ©cosystĂšme Node.js aujourdâhui).
- soit vous passez par un service de redimensionnement dâimage comme Cloudinary, imgix, etc. Ces services vous permettent dâuploader une premiĂšre image en grande taille, puis vous met Ă dispositions des URLs qui, Ă lâaide de paramĂštres, vous permettent de gĂ©nĂ©rer des tailles Ă la demande.
- Cloudinary :
/w_500/h_200/
- Imgix:
w=500&h=200
- TwicPics:
cover=500x200
- Il existe aussi des services que vous pouvez hĂ©berger vous-mĂȘme : Pixboost/transformimgs, serverless-image-handler
- Cloudinary :
A noter quâici je parle uniquement de redimensionnement, mais il existe dans sharp ou dans les solutions SaaS beaucoup dâoptions (cover/crop, focal point, manipulation dâimage, etc.). NâhĂ©sitez pas Ă fouiller dans celles-ci afin de trouver le process qui vous convient le mieux.
4. Transformer notre <img>
en <picture>
Une fois les images générées passons au HTML. Initialement, il ressemblait à ceci :
<img
alt="Description de l'image"
src="/images/image.jpg"
loading="lazy"
/>
Pour lâadapter au tableau de la section 2., nous allons devoir utiliser 2 nouvelles balises : <source>
et <picture>
.
<source>
définit le type de sources disponibles grùce à ses attributsmedia
 : indique le format dâĂ©cran pour lequel la source est Ă©ligiblesrcset
 : indique quelle image charger en fonction de la densitĂ© de lâĂ©cran
<picture>
indique que plusieurs sources dâimages sont disponibles et quâil peut choisir la premiĂšre qui est compatible. En plus de la liste de<source>
, il faut conserver la balise<img>
en tant quâenfant de<picture>
, elle servira de source par défaut pour votre navigateur.
Si on fait le rapprochement avec notre tableau, cela veut dire quâon va avoir :
- une
<source>
par ligne du tableau, en reprenant la media query - une URL dâimage dans srcset par pixel ratio
- la balise
<img>
qui correspond Ă la derniĂšre ligne du tableau
<picture>
<source
media="(min-width: 1000px)"
srcset="
/images/image-336x240.jpg 1x
/images/image-672x480.jpg 2x
"
/>
<source
media="(min-width: 600px)"
srcset="/images/image-480x600.jpg 2x"
/>
<source
media="(min-width: 416px)"
srcset="/images/image-1070x416.jpg 2x"
/>
<img
alt="Description de l'image"
src="/images/image-622x416.jpg"
loading="lazy"
/>
</picture>
Et voilĂ , on a rĂ©ussi Ă fournir la bonne taille au navigateurâŻ! Si vous inspectez votre navigateur, vous verrez quâĂ chaque rafraĂźchissement de page dans des dimensions diffĂ©rentes, câest la bonne image qui est chargĂ©e.
5. FAQ â
Si vous vous ĂȘtes dĂ©jĂ frottĂ© aux images responsives, aux srcset
et compagnie, vous trouvez peut-ĂȘtre que je suis allĂ© un peu vite en besogne. NâhĂ©sitez pas Ă dĂ©plier les questions ci-dessous pour entrer plus en dĂ©tails dans certains aspects.
Comment se comporte la balise <picture>
d'un point de vue CSS ?
GrossiĂšrement, vous pouvez considĂ©rer quâune <picture>
se comporte comme un <span>
. Ca nâaffiche rien de particulier dans votre page et se comporte donc plus ou moins de la mĂȘme façon que si vous avez une balise <img>
directement.
Cela dit, ce nouveau niveau de balise peut parfois poser des problĂšmes quand vous utilisez des Flexbox, des Grids ou autres outils de positionnement. Une solution pour cela est de lui assigner display: contents
ou de lui appliquer les mĂȘmes rĂšgles que si vous aviez une div
(height: 100%
, align-self: stretch
ou autre).
Que se passe-t-il si la taille de mon image dépend aussi de la hauteur du navigateur ?
Dans notre exemple nous avions dans notre code CSS uniquement des media queries en largeur (min-width
) et pas dâunitĂ©s basĂ©s sur vh
. Cependant il est possible que vous ayez besoin de charger une image différente si vous tenez à ce que votre image tienne toujours en hauteur dans votre écran (ex : max-height: 80vh
).
A ce moment lĂ il faudra complexifier votre tableau. Au lieu dâavoir des media queries Ă une dimension, vous pourrez les combiner : (min-width: 1000px) and (min-height: 720px)
.
Est-ce possible d'éviter les <source>
et de se contenter de srcset
et sizes
? On est passé par des descripteurs 1x
et 2x
mais ce n'est pas mieux de passer par 622w
?
RĂ©ponse courte : non đ Si vous passez par ces solutions alternatives, vous vous retrouverez soit avec des images pixellisĂ©es, soit avec des images trop lourdes. Je mâexplique.
sizes
est un attribut quâon peut mettre sur <img>
(ou sur <source>
), pour dĂ©finir quelle taille utiliser en fonction de quelle media query. Si on reprend notre tableau, câest un peu la combinaison des colonnes Media Query et CSS Image Size. La diffĂ©rence est quâil nây a pas besoin de connaĂźtre le type de devices qui visitent notre site parce quâon se contente de dĂ©crire factuellement les diffĂ©rentes tailles dâimages pour tous les devices. Cela va ressembler globalement Ă quelque chose de ce style :
<img
sizes="
(min-width: 1000px) 336px,
(min-width: 600px) 240px,
95vw
"
/>
En combinaison avec lâattribut srcset, cela permet au navigateur, si on lui donne une liste dâimage Ă©lligible, de choisir celle qui correspondra le mieux.
<img
srcset="
/images/image-336x240.jpg 336w,
/images/image-480x600.jpg 480w,
/images/image-622x416.jpg 622w,
/images/image-672x480.jpg 672w,
/images/image-1070x416.jpg 1070w
"
sizes="
(min-width: 1000px) 336px,
(min-width: 600px) 240px,
95vw
"
/>
Vous pouvez constater que dans le srcset
, jâai utilisĂ© le descripteur w
en fin de ligne. Celui-ci dit au navigateur non pas quelle densitĂ© de pixel a le droit dâutiliser cette image, mais combien de pixels physiques sont prĂ©sents dans lâimage.
Charge au navigateur donc de choisir la bonne. Si je suis sur un iPhone de 375px, avec un devicePixelRatio = 3, alors il va comprendre quâil a besoin dâune image de 375 * 0.95 (grĂące Ă lâattribute sizes) * 3 (devicePixelRatio) = 1068w.
La plus proche est /images/image-1070x416.jpg
donc câest celle lĂ quâil choisit.
Dommage, nous on lui avait juste besoin de 622x416. Le navigateur aurait pu tĂ©lĂ©charger 40% moins dâoctets pour fournir la mĂȘme qualitĂ© de service Ă lâutilisateurice.
Plus gĂȘnant, il peut arriver des cas oĂč lâimage choisie nâaura pas assez de pixels en hauteur. Prenons un exemple trĂšs frĂ©quent : une image de banniĂšre (sizes=â100vwâ) qui a la rĂšgle CSS height: 15rem
(= 240px). Pour bien faire je vais donc mettre Ă disposition mes images en x2 sur mobile et x1 + x2 sur desktop.
Device Width | Media Query | CSS Image Size | Pixel Ratio | Physical Image Size |
---|---|---|---|---|
1980 | (min-width: 1440px) | 1980 x 240 | 1x | 1980 x 240 |
2x | 3960 x 480 | |||
1439 | (min-width: 1280px) | 1439 x 240 | 1x | 1439 x 240 |
2x | 2878 x 480 | |||
1279 | (min-width: 768px) | 1279 x 240 | 1x | 1279 x 240 |
2x | 2558 x 480 | |||
767 | (min-width: 416px) | 767 x 240 | 2x | 1534 x 480 |
375 | 375 x 240 | 2x | 750 x 480 |
Et donc avec un srcset unique, cela donneraĂźt ceci (jâai triĂ© les images par taille croissante pour plus de clartĂ©):
<img
srcset="
/images/image-750x480.jpeg 750w,
/images/image-1279x240.jpeg 1279w,
/images/image-1439x240.jpeg 1439w,
/images/image-1534x480.jpeg 1534w,
/images/image-1980x240.jpeg 1980w,
/images/image-2558x480.jpeg 2558w,
/images/image-2878x480.jpeg 2878w,
/images/image-3960x480.jpeg 3960w
"
sizes="100vw"
/>
Donc avec cette nouvelle image, reprenons mon exemple de tout Ă lâheure : je suis sur un device de 375px avec une densitĂ© 3x. Alors il me faut une image de 1125 pixels physiques. Lâimage la plus proche est 1279 x 240.
Lâutilisateurice se retrouve avec une image qui est maintenant trop grande en largeur, mais trop petite en hauteur. Le ratio est totalement dĂ©formĂ©, et lâimage devient floue Ă lâĂ©cran.

Ce cas est reprĂ©sentatif de la majoritĂ© des images avec lesquelles jâai pu travailler.
Il reste tout de mĂȘme un dernier cas : celui pour lequel le ratio de lâimage est toujours strictement identique. Ainsi, lâimage est toujours correctement affichĂ©e, mais il nous reste le problĂšme de la densitĂ© de pixel trop Ă©levĂ©e.
En effet, les derniers iPhones ont une densitĂ© de 3x. Il paraĂźt que câest censĂ© rendre les affichages plus extraordinaires. En pratique, ça ne sert Ă rien si ce nâest consommer plus de bande passante et dâĂ©nergie. Un jour, peut-ĂȘtre que les navigateurs le gĂ©reront directement. En attendant, limitons manuellement la taille des images tĂ©lĂ©chargĂ©es par exemple en utilisant la mĂ©thode des <source>
montrée plus haut.
Choisir le bon format dâimage
Nous avons vu comment choisir la bonne taille pour nos images. Mais il y a un autre levier que nous pouvons utiliser pour améliorer leur performance : le type de fichier (ou format).
Historiquement, les images sur le web étaient réparties sur deux formats :
- JPEG : trĂšs rĂ©pandu, il permet de choisir son niveau de qualitĂ©. GĂ©nĂ©ralement, on le repĂšre parce quâil a tendance Ă crĂ©er des petits artefacts qui dĂ©forment lâimage. On prĂ©fĂšre lâutiliser pour toute image qui ne repose pas principalement sur des aplats de couleur.
- PNG : la seule option pendant longtemps pour gĂ©rer les images transparentes. Câest un format lossless : en lâutilisant, la qualitĂ© de lâimage reste intacte. Au-delĂ des images transparentes, on prefĂšre aussi lâutiliser dĂšs que les images sont constituĂ©es dâapplats de couleur, avec peu de dĂ©gradĂ©s. Dans ces conditions, il performe mieux que le JPEG.
Cependant, en allant chercher toujours plus dâoptimisations des gens vachement intelligent·e·s ont fait apparaĂźtre dâautres formats :
- WEBP : plus petit de ~30% que JPEG et PNG, il est capable de gĂ©rer la transparence. De nos jours, ça peut ĂȘtre le nouveau format par dĂ©faut, Ă quelques exceptions prĂšs (~95% des devices).
- AVIF : plus petit de ~30% que WEBP, il gĂšre lui aussi la transparence. Il nâest toutefois pas supportĂ© partout avec un support inexistant sur Edge et trĂšs rĂ©cent seulement sur Safari (~82% des devices).
- JPEG XL : niveau de performance similaire Ă AVIF. Il semble ĂȘtre meilleur sur des compressions lossless (source : JPEG XL vs AVIF: A Comparison). Cependant, lâintĂ©rĂȘt majeur est vis a vis de son dĂ©codage progressif qui change drastiquement la performance ressentie. Ce format est aujourdâhui uniquement supportĂ© par la toute derniĂšre version de Safari et bientĂŽt sur Firefox. Il est donc trop tĂŽt mais ça sâannonce trĂšs prometteur.
Enfin, je nâen parle pas ici, mais si vous avez des images vectorielles (gĂ©nĂ©ralement pour des logo, des icons ou des schema) vous pouvez directement utiliser du SVG.
Cela fait donc tout un tas de format Ă avoir en tĂȘte. Mais le niveau de support des navigateurs est trĂšs fragmentĂ©. Comment faire pour gĂ©rer tous les casâŻ?
Se reposer sur la détection automatique
Pour gĂ©nĂ©rer des images de diffĂ©rentes tailles, je vous parlais tout Ă lâheure de services en ligne qui vous permettent de redimensionner votre image directement via des paramĂštres au niveau de lâURL. Ces mĂȘmes services proposent gĂ©nĂ©ralement une option pour transformer votre image dans le format le plus optimisĂ©. En effet, lorsque votre navigateur essaye de tĂ©lĂ©charger une image, il va faire une requĂȘte avec un Header Accept
qui définit quels formats sont supportés :
Accept: image/avif,image/webp,image/apng,image/svg+xml,image/_,_/\*;q=0.8
Ainsi, Ă partir de ce header, le serveur qui reçoit la requĂȘte sait quâil peut renvoyer du AVIF (image/avif
) et du WEBP (image/webp
) mais pas de JPEG XL par exemple. Pour activer cette option, vous pouvez utiliser les paramÚtres suivants :
- Cloudinary :
f_auto
- imgix:
auto=format
- TwicPics:
output=auto
đĄ Vous avez peut-ĂȘtre entendu parler du fait que le format AVIF est plus lent Ă gĂ©nĂ©rer que les autres formats. CâĂ©tait vrai au dĂ©but, mais il paraĂźt que ce nâest plus le cas. Pour cette raison, nombres des services sus-citĂ©s ne proposent pas par dĂ©faut de lâAVIF. NâhĂ©sitez donc pas Ă vous rĂ©fĂ©rer Ă leur documentation pour voir comment ils gĂšrent la situation.
Toutefois, vous nâavez pas forcĂ©ment accĂšs Ă ces outils. Comment faire alors pour le gĂ©rer directement avec du HTMLâŻ?
Utiliser lâattribut type
sur vos <source>
Tout Ă lâheure quand nous avions construit le HTML pour mettre Ă disposition les diffĂ©rentes tailles dâimages, je vous avais dit que <source>
avait les attributs media
et srcset
. Il va en accepter un troisiÚme : type="image/xxx"
.
En ajoutant ce nouvel attribut, vous indiquez au navigateur quâil ne doit prendre en compte cette source que sâil supporte le format indiquĂ©. Ainsi, si vous voulez supporter Ă la fois du jpeg ET du webp, vous allez devoir dupliquer vos sources.
Attention, lâordre reste important : câest la premiĂšre source qui est compatible avec le navigateur qui sera choisie. Les sources de type image/webp
doivent donc apparaĂźtre avant les sources de type image/jpeg
.
<picture>
+ <source
+ type="image/webp"
+ media="(min-width: 1000px)"
+ srcset="
+ /images/image-336x240.webp 1x
+ /images/image-672x480.webp 2x
+ "
+ />
<source
+ type="image/jpeg"
media="(min-width: 1000px)"
srcset="
/images/image-336x240.jpg 1x
/images/image-672x480.jpg 2x
"
/>
+ <source
+ type="image/webp"
+ media="(min-width: 600px)"
+ srcset="/images/image-480x600.webp 2x"
+ />
<source
+ type="image/jpeg"
media="(min-width: 600px)"
srcset="/images/image-480x600.jpg 2x"
/>
+ <source
+ type="image/webp"
+ media="(min-width: 416px)"
+ srcset="/images/image-1070x416.webp 2x"
+ />
<source
+ type="image/jpeg"
media="(min-width: 416px)"
srcset="/images/image-1070x416.jpg 2x"
/>
+ <source
+ type="image/webp"
+ srcset="/images/image-622x416.webp"
+ />
<img
alt="Description de l'image"
src="/images/image-622x416.jpg"
loading="lazy"
/>
</picture>
Comme vous pouvez le voir, cela devient vite trĂšs verbeux. Essayez donc au maximum de vous reposer sur la dĂ©tection automatique. Câest dâautant plus vrai que pour supporter un maximum de navigateurs, il faudrait 4 formats : JPEG, WEBP, AVIF & JPEG XL. Vous vous retrouveriez donc avec 16 balises <source>
différentes.
Preload une image responsive
Nous sommes maintenant capables de fournir au navigateur une image de la bonne taille et du bon format en toute circonstance. Il nous reste un dernier point à voir ensemble avant de nous quitter : comment est-ce que ces nouveaux outils impactent le preload des images�
En effet, nous avions vu dans lâarticle prĂ©cĂ©dent que preloader les images critiques pouvait avoir un impact sur le LCP. Pour cela, nous avions dĂ» ajouter une balise <link>
dans le <head>
 :
<link
rel="preload"
as="image"
type="image/jpeg"
href="/images/banner.jpg"
fetchpriority="high"
/>
Mais comme vous pouvez le voir, cela ne prend en compte quâune seule URL dâimage. Si vous voulez preload la bonne image en fonction de lâappareil utilisĂ©, vous allez devoir multiplier vos balises <link>
pour quâelles ressemblent aux balises <source>
de votre image. Cela peut se faire notamment en transformat les attributs:
srcset
devientimagesrcset
sizes
devientimagesizes
type
restetype
(facultatif si vous vous reposez sur de la détection automatique)
<link
rel="preload"
as="image"
media="(min-width: 1000px)"
imagesrcset="
/images/image-336x240.jpg 1x
/images/image-672x480.jpg 2x
"
/>
<link
rel="preload"
as="image"
media="(min-width: 600px)"
imagesrcset="/images/image-480x600.jpg 2x"
/>
<link
rel="preload"
as="image"
media="(min-width: 416px)"
imagesrcset="/images/image-1070x416.jpg 2x"
/>
<link
rel="preload"
as="image"
href="/images/image-622x416.jpg"
/>
Cependant, simplement renommer les attributs nâest pas suffisant. En effet, si vous mettez ça dans votre page et que vous chargez la page sur desktop, vous constaterez que 4 images seront preloadĂ©es au lieu dâune seule. Cela vient du fait que les balises <link>
ne sont pas rassemblées sous une balise <picture>
. Le navigateur ne sait donc pas quâil en a besoin dâune seule et va toutes les tĂ©lĂ©charger.
Il vous faut donc transformer les media
afin quâelles contiennent un min-width
ET un max-width
.
<link
rel="preload"
as="image"
media="(min-width: 1000px)"
imagesrcset="
/images/image-336x240.jpg 1x
/images/image-672x480.jpg 2x
"
/>
<link
rel="preload"
as="image"
- media="(min-width: 600px)"
+ media="(min-width: 600px) and (max-width: 999px)"
imagesrcset="/images/image-480x600.jpg 2x"
/>
<link
rel="preload"
as="image"
- media="(min-width: 416px)"
+ media="(min-width: 416px) and (max-width: 599px)"
imagesrcset="/images/image-1070x416.jpg 2x"
/>
<link
rel="preload"
as="image"
+ media="(max-width: 415px)"
href="/images/image-622x416.jpg"
/>
Cette fois-ci câest la bonne : le navigateur va ĂȘtre capable de nâen charger quâune seule.
Définir les attributs width
et height
pour régler le problÚmes de Layout Shifts
Avant de nous quitter, il y a un dernier Ă©lĂ©ment que jâaimerais que vous ayez en tĂȘte quand vous dĂ©finissez vos images. Pour cela, observons la diffĂ©rence entre les deux chargements suivants :
Petit indice, câest particuliĂšrement visible Ă 3.3s de chargement.
En effet, sur le chargement de gauche, on voit pendant un court instant le bandeau noir de fin de page. Puis, dans les instants qui suivent, le contenu bouge un peu dans tous les sens au fur et Ă mesure que les images arrivent. Câest ce quâon appel du Layout Shift : un Ă©lĂ©ment sâest dĂ©placĂ© sans action de la part de lâutilisateurice.
Câest un problĂšme parce que si une personne commence Ă lire le bandeau noir puis que les images commencent Ă arriver, dĂ©calant ainsi le contenu, alors elle va perdre le fil de sa lecture. Il va falloir scroller â parfois trĂšs loin â jusquâĂ retrouver le contenu qui lâintĂ©ressait. Pire, si jamais la personne cherche Ă cliquer quelque part, et que juste avant de cliquer le contenu se dĂ©cale, elle pourra faire la mauvaise action, menant Ă beaucoup de frustration.
Cela fait partie des indicateurs de performance qui sont observĂ©s par les Core Web Vitals : le CLS (Cumulative Layout Shift) et peut impacter votre SEO en plus de dĂ©teriorer lâexpĂ©rience de vos utilisateurices.
Le moyen le plus simple et souvent suffisant est dâajouter les attributs width
et height
sur vos images. Il sâagit de la valeur en CSS Pixels.
<picture>
<source
media="(min-width: 1000px)"
srcset="
/images/image-336x240.jpg 1x
/images/image-672x480.jpg 2x
"
/>
<source
media="(min-width: 600px)"
srcset="/images/image-480x600.jpg 2x"
/>
<source
media="(min-width: 416px)"
srcset="/images/image-1070x416.jpg 2x"
/>
<img
alt="Description de l'image"
src="/images/image-622x416.jpg"
loading="lazy"
+ width="311"
+ height="208"
/>
</picture>
En ajoutant ces attributs, le navigateur va ĂȘtre en mesure de comprendre lâaspect-ratio
de vos images et donc rĂ©server suffisamment de place pour Ă©viter les sauts de contenus. Câest le seul changement que jâai mis en place sur la partie droite de la vidĂ©o. Un petit changement comparĂ© au bĂ©nĂ©fice que ça apporte Ă lâutilisateurice. Donc un bon rĂ©flexe Ă prendre.
Récapitulatif
Maintenant que nous avons vu la thĂ©orie, quâest-ce que ça donne en pratiqueâŻ? Est-ce que mettre en place tout ça amĂ©liore rĂ©ellement les performances de nos pagesâŻ? Vous vous en doutez, si jâen vous parle, câest que la rĂ©ponse est oui. Mais concrĂštement, jâai mis cela en place sur toutes les images de la page dâexemple. Et grĂące Ă cela, on passe de 2.4s de LCP Ă 1.8s, soit -25%âŻ! đ


Câest donc rĂ©ellement quelque chose qui peut drastiquement changer la performance ressentie de vos pages.
Afin que vous puissiez bĂ©nĂ©ficier des mĂȘmes gains sur votre site, et parce quâil est difficile de garder en tĂȘte la totalitĂ© des bonnes pratiques, voici une checklist pour rester rigoureux·se et qui pourra vous servir de pense-bĂȘte :
<img>
normale- Snippet
<picture>
et<source>
dans votre HTMLfetchpriority
width
&height
sur la balise<img>
pour Ă©viter des problĂšmes de Layout Shift (article Ă ce sujet Ă venir đ)- Lighthouse ou WebPageTest afin de vĂ©rifier que tout est bon
- Mastodon ou Twitter pour cĂ©lĂ©brer la victoire đ
Si vous avez toujours soif de Web Performance, sachez que je publie en ce moment un article par semaine Ă ce sujet. NâhĂ©sitez donc pas Ă me suivre sur les rĂ©seaux sociaux et Ă partager cet article, cela contribuera Ă me motiver Ă tenir le rythme đ
Pour rappel, je suis aussi disponible en freelance et peut travailler avec vous sur vos travaux en rapport avec la web performance. Que vous ayez des lenteurs déjà identifiées ou que vous ayez besoin de savoir si oui ou non la performance est un enjeux pour votre entreprise, je peux vous aider.
Dans tous les cas, la semaine prochaine nous parlerons optimisation des fonts, stay tunedâŻ!
Si vous voulez suivre mes publications, il paraĂźt que j'ai un feed RSS, Mastodon et un Twitter.
Si vous pensez à d'autres méthodes que vous voudriez que je mette en place (pigeon voyageur, avion en papier, etc.), n'hésitez pas à me les proposer :)