Les images sont souvent la ressource la plus lourde et la plus courante sur le Web. Par conséquent, optimiser les images peut considérablement améliorer les performances de votre site Web. Dans la plupart des cas, l'optimisation des images consiste à réduire le temps réseau en envoyant moins d'octets. Vous pouvez également optimiser la quantité d'octets envoyés à l'utilisateur en diffusant des images de la bonne taille pour son appareil.
Vous pouvez ajouter des images à une page à l'aide des éléments <img>
ou <picture>
, ou de la propriété CSS background-image
.
Taille d'image
La première optimisation que vous pouvez effectuer lorsque vous utilisez des ressources d'image consiste à afficher l'image à la bonne taille. Dans ce cas, le terme taille fait référence aux dimensions d'une image. En ne tenant compte d'aucune autre variable, une image affichée dans un conteneur de 500 x 500 pixels aurait une taille optimale de 500 x 500 pixels. Par exemple, si vous utilisez une image carrée de 1 000 pixels, cela signifie qu'elle est deux fois plus grande que nécessaire.
Toutefois, le choix de la taille d'image appropriée implique de nombreuses variables, ce qui rend la tâche de choisir la taille d'image appropriée dans chaque cas assez compliquée. En 2010, lorsque l'iPhone 4 est sorti, la résolution de l'écran (640 x 960) était le double de celle de l'iPhone 3 (320 x 480). Cependant, la taille physique de l'écran de l'iPhone 4 est à peu près la même que celle de l'iPhone 3.
Afficher tout à la résolution supérieure aurait rendu le texte et les images beaucoup plus petits (la moitié de leur taille précédente, pour être exact). Au lieu de cela, un pixel est devenu deux pixels de l'appareil. C'est ce qu'on appelle le rapport de pixels de l'appareil (DPR). L'iPhone 4 (et de nombreux modèles d'iPhone sortis après lui) avait un DPR de 2.
Pour reprendre l'exemple précédent, si l'appareil a un DPR de 2 et que l'image est affichée dans un conteneur de 500 x 500 pixels, une image carrée de 1 000 pixels (appelée taille intrinsèque) est désormais la taille optimale. De même, si l'appareil a un DPR de 3, une image carrée de 1 500 pixels est la taille optimale.
srcset
L'élément <img>
accepte l'attribut srcset
, qui vous permet de spécifier une liste de sources d'images possibles que le navigateur peut utiliser. Chaque source d'image spécifiée doit inclure l'URL de l'image et un descripteur de largeur ou de densité de pixels.
<img
alt="An image"
width="500"
height="500"
src="/image-500.jpg"
srcset="/image-500.jpg 1x, /image-1000.jpg 2x, /image-1500.jpg 3x"
>
L'extrait HTML précédent utilise le descripteur de densité de pixels pour indiquer au navigateur d'utiliser image-500.png
sur les appareils avec un DPR de 1, image-1000.jpg
sur les appareils avec un DPR de 2 et image-1500.jpg
sur les appareils avec un DPR de 3.
Bien que tout cela puisse sembler simple, le DPR d'un écran n'est pas le seul facteur à prendre en compte pour choisir l'image optimale pour une page donnée. La mise en page de la page est un autre élément à prendre en compte.
sizes
La solution précédente ne fonctionne que si vous affichez l'image à la même taille de pixel CSS sur tous les viewports. Dans de nombreux cas, la mise en page d'une page (et la taille du conteneur avec elle) change en fonction de l'appareil de l'utilisateur.
L'attribut sizes
vous permet de spécifier un ensemble de tailles de source, où chaque taille de source se compose d'une condition multimédia et d'une valeur. L'attribut sizes
décrit la taille d'affichage prévue de l'image en pixels CSS. Combiné aux descripteurs de largeur srcset
, le navigateur peut choisir la source d'image la plus adaptée à l'appareil de l'utilisateur.
<img
alt="An image"
width="500"
height="500"
src="/image-500.jpg"
srcset="/image-500.jpg 500w, /image-1000.jpg 1000w, /image-1500.jpg 1500w"
sizes="(min-width: 768px) 500px, 100vw"
>
Dans l'extrait HTML précédent, l'attribut srcset
spécifie une liste d'images candidates parmi lesquelles le navigateur peut choisir, séparées par des virgules. Chaque candidat de la liste se compose de l'URL de l'image, suivie d'une syntaxe qui indique la largeur intrinsèque de l'image. La taille intrinsèque d'une image correspond à ses dimensions. Par exemple, un descripteur 1000w
indique que la largeur intrinsèque de l'image est de 1 000 pixels.
À l'aide de ces informations, le navigateur évalue la condition multimédia dans l'attribut sizes
et, dans ce cas, est informé que si la largeur de la fenêtre d'affichage de l'appareil dépasse 768 pixels, l'image est affichée sur une largeur de 500 pixels. Sur les appareils plus petits, l'image est affichée à 100vw
, soit la largeur complète de la vue d'ensemble.
Le navigateur peut ensuite combiner ces informations avec la liste des sources d'images srcset
pour trouver l'image optimale. Par exemple, si l'utilisateur se trouve sur un appareil mobile dont la largeur d'écran est de 320 pixels avec un DPR de 3, l'image s'affiche à 320 CSS pixels x 3 DPR = 960 device pixels
. Dans cet exemple, l'image de taille la plus proche est image-1000.jpg
, qui a une largeur intrinsèque de 1 000 pixels (1000w
).
Formats des fichiers
Les navigateurs sont compatibles avec plusieurs formats de fichiers image différents. Les formats d'image modernes tels que WebP et AVIF peuvent offrir une meilleure compression que les formats PNG ou JPEG. Ils réduisent ainsi la taille de vos fichiers image, ce qui réduit le temps de téléchargement. En diffusant des images dans des formats modernes, vous pouvez réduire le temps de chargement d'une ressource, ce qui peut entraîner une diminution du LCP (Largest Contentful Paint).
WebP est un format largement compatible qui fonctionne sur tous les navigateurs modernes. WebP offre souvent une meilleure compression que JPEG, PNG ou GIF, et propose à la fois une compression avec pertes et une compression sans perte. WebP est également compatible avec la transparence du canal alpha, même lors de l'utilisation d'une compression avec pertes, une fonctionnalité que le codec JPEG n'offre pas.
AVIF est un format d'image plus récent. Bien qu'il ne soit pas aussi largement pris en charge que WebP, il bénéficie d'une compatibilité raisonnable dans les navigateurs. AVIF est compatible avec la compression avec pertes et sans perte. Des tests ont montré des économies de plus de 50% par rapport au format JPEG dans certains cas. L'AVIF propose également des fonctionnalités Wide Color Gamut (WCG) et High Dynamic Range (HDR).
Compression
En ce qui concerne les images, il existe deux types de compression:
La compression avec perte consiste à réduire la précision de l'image via la quantisation. Des informations de couleur supplémentaires peuvent être supprimées à l'aide du sous-échantillonnage chromatique. La compression avec perte est la plus efficace sur les images haute densité avec beaucoup de bruit et de couleurs, généralement des photos ou des images avec des contenus similaires. En effet, les artefacts produits par la compression avec perte sont beaucoup moins susceptibles d'être remarqués dans des images aussi détaillées. Toutefois, la compression avec pertes peut être moins efficace avec des images contenant des arêtes nettes, comme des illustrations, des détails nets ou du texte. La compression avec pertes peut être appliquée aux images JPEG, WebP et AVIF.
La compression sans perte réduit la taille du fichier en compressant une image sans perte de données. La compression sans perte décrit un pixel en fonction de la différence avec ses pixels voisins. La compression sans perte est utilisée pour les formats d'image GIF, PNG, WebP et AVIF.
Vous pouvez compresser vos images à l'aide de Squoosh, de ImageOptim ou d'un service d'optimisation des images. Lors de la compression, il n'existe pas de paramètre universel adapté à tous les cas. Nous vous recommandons de tester différents niveaux de compression jusqu'à trouver un bon compromis entre la qualité de l'image et la taille du fichier. Certains services d'optimisation d'images avancés peuvent le faire automatiquement pour vous, mais ils ne sont pas forcément financièrement viables pour tous les utilisateurs.
L'élément <picture>
L'élément <picture>
vous permet de spécifier plusieurs images candidates plus facilement:
<picture>
<source type="image/avif" srcset="image.avif">
<source type="image/webp" srcset="image.webp">
<img
alt="An image"
width="500"
height="500"
src="/image.jpg"
>
</picture>
Lorsque vous utilisez un ou plusieurs éléments <source>
dans l'élément <picture>
, vous pouvez ajouter la prise en charge des images AVIF et WebP, mais revenir aux anciens formats d'image plus compatibles si le navigateur n'est pas compatible avec les formats modernes. Avec cette approche, le navigateur sélectionne le premier élément <source>
spécifié qui correspond. S'il peut afficher l'image dans ce format, il l'utilise. Sinon, le navigateur passe à l'élément <source>
suivant spécifié. Dans l'extrait HTML précédent, le format AVIF est prioritaire sur le format WebP, et le format JPEG est utilisé si ni AVIF ni WebP ne sont compatibles.
Un élément <picture>
nécessite un élément <img>
imbriqué. Les attributs alt
, width
et height
sont définis sur le <img>
et utilisés quel que soit le <source>
sélectionné.
L'élément <source>
accepte également les attributs media
, srcset
et sizes
. Comme dans l'exemple <img>
précédent, ils indiquent au navigateur l'image à sélectionner dans différents viewports.
<picture>
<source
media="(min-resolution: 1.5x)"
srcset="/image-1000.jpg 1000w, /image-1500.jpg 1500w"
sizes="(min-width: 768px) 500px, 100vw"
>
<img
alt="An image"
width="500"
height="500"
src="/image-500.jpg"
>
</picture>
L'attribut media
utilise une condition multimédia. Dans l'exemple précédent, la DPR de l'appareil est utilisée comme condition multimédia. Tout appareil dont le DPR est supérieur ou égal à 1,5 utilisera le premier élément <source>
. L'élément <source>
indique au navigateur que, sur les appareils dont la largeur de la vue d'affichage est supérieure à 768 pixels, l'image candidate sélectionnée est affichée sur 500 pixels de large. Sur les appareils plus petits, cela occupe toute la largeur de la fenêtre d'affichage. En combinant les attributs media
et srcset
, vous pouvez contrôler plus précisément l'image à utiliser.
Cela est illustré dans le tableau suivant, où plusieurs largeurs de vue et formats de pixel de l'appareil sont évalués:
Largeur de la fenêtre d'affichage (pixels) | 1 DPR | 1,5 DPR | 2 DPR | 3 DPR |
---|---|---|---|---|
320 | 500.jpg | 500.jpg | 500.jpg | 1000.jpg |
480 | 500.jpg | 500.jpg | 1000.jpg | 1500.jpg |
560 | 500.jpg | 1000.jpg | 1000.jpg | 1500.jpg |
1024 | 500.jpg | 1000.jpg | 1000.jpg | 1500.jpg |
1920 | 500.jpg | 1000.jpg | 1000.jpg | 1500.jpg |
Les appareils avec un DPR de 1 téléchargent l'image image-500.jpg
, y compris la plupart des utilisateurs de bureau, qui affichent l'image avec une taille extrinsèque de 500 pixels de large. En revanche, les utilisateurs mobiles avec un DPR de 3 téléchargent une image-1500.jpg
potentiellement plus grande, la même image utilisée sur les ordinateurs de bureau avec un DPR de 3.
<picture>
<source
media="(min-width: 561px) and (min-resolution: 1.5x)"
srcset="/image-1000.jpg 1000w, /image-1500.jpg 1500w"
sizes="(min-width: 768px) 500px, 100vw"
>
<source
media="(max-width: 560px) and (min-resolution: 1.5x)"
srcset="/image-1000-sm.jpg 1000w, /image-1500-sm.jpg 1500w"
sizes="(min-width: 768px) 500px, 100vw"
>
<img
alt="An image"
width="500"
height="500"
src="/image-500.jpg"
>
</picture>
Dans cet exemple, l'élément <picture>
est ajusté pour inclure un élément <source>
supplémentaire afin d'utiliser différentes images pour les appareils larges avec un DPR élevé:
Largeur de la fenêtre d'affichage (pixels) | 1 DPR | 1,5 DPR | 2 DPR | 3 DPR |
---|---|---|---|---|
320 | 500.jpg | 500.jpg | 1000-sm.jpg | 1000-sm.jpg |
480 | 500.jpg | 500.jpg | 1000-sm.jpg | 1500-sm.jpg |
560 | 500.jpg | 1000-sm.jpg | 1000-sm.jpg | 1500-sm.jpg |
1024 | 500.jpg | 1000.jpg | 1000.jpg | 1500.jpg |
1920 | 500.jpg | 1000.jpg | 1000.jpg | 1500.jpg |
Avec cette requête supplémentaire, vous pouvez voir que image-1000-sm.jpg
et image-1500-sm.jpg
s'affichent sur de petits viewports. Ces informations supplémentaires vous permettent de compresser davantage les images, car les artefacts de compression ne sont pas très visibles à cette taille et à cette densité, tout en préservant la qualité de l'image sur les appareils de bureau.
Vous pouvez également éviter de diffuser de grandes images sur de petites fenêtres d'affichage en ajustant les attributs srcset
et media
:
<picture>
<source
media="(min-width: 561px)"
srcset="/image-500.jpg, /image-1000.jpg 2x, /image-1500.jpg 3x"
>
<source
media="(max-width: 560px)"
srcset="/image-500.jpg 1x, /image-1000.jpg 2x"
>
<img
alt="An image"
width="500"
height="500"
src="/image-500.jpg"
>
</picture>
Dans l'extrait HTML précédent, les descripteurs de largeur ont été supprimés au profit des descripteurs de format de pixel de l'appareil. Les images diffusées sur un appareil mobile sont limitées à /image-500.jpg
ou /image-1000.jpg
, même sur les appareils dont la DPR est de 3.
Gérer la complexité
Lorsque vous travaillez avec des images responsives, vous pouvez vous retrouver avec de nombreuses variations de taille et de formats pour chaque image. Dans l'exemple précédent, des variantes pour chaque taille sont utilisées, mais excluent AVIF et WebP. Combien de variantes devez-vous avoir ? Comme pour de nombreux problèmes d'ingénierie, la réponse tend à être "ça dépend".
Bien qu'il puisse être tentant d'avoir autant de variantes que possible pour obtenir la meilleure adéquation, chaque variante d'image supplémentaire a un coût et utilise moins efficacement le cache du navigateur. Avec une seule variante, chaque utilisateur reçoit la même image, ce qui permet de la mettre en cache de manière très efficace.
En revanche, si vous avez de nombreuses variantes, chacune d'elles nécessite une autre entrée de cache. Les coûts du serveur peuvent augmenter et les performances peuvent être dégradées si l'entrée de cache de la variante a expiré et que l'image doit être récupérée à nouveau à partir du serveur d'origine.
En outre, la taille de votre document HTML augmente avec chaque variante. Vous pouvez envoyer plusieurs kilo-octets de code HTML pour chaque image.
Diffuser des images en fonction de l'en-tête de requête Accept
L'en-tête de requête HTTP Accept
informe le serveur des types de contenu que le navigateur de l'utilisateur comprend. Votre serveur peut utiliser ces informations pour diffuser le format d'image optimal sans ajouter d'octets supplémentaires à vos réponses HTML.
if (request.headers.accept) {
if (request.headers.accept.includes('image/avif')) {
return reply.from('image.avif');
} else if (request.headers.accept.includes('image/webp')) {
return reply.from('image.webp');
}
}
return reply.from('image.jpg');
L'extrait HTML précédent est une version simplifiée du code que vous pouvez ajouter au backend JavaScript de votre serveur pour choisir et diffuser le format d'image optimal.
Si l'en-tête Accept
de la requête inclut image/avif
, l'image AVIF est diffusée. Sinon, si l'en-tête Accept
inclut image/webp
, l'image WebP est diffusée. Si aucune de ces conditions n'est remplie, l'image JPEG est diffusée.
Vous pouvez modifier les réponses en fonction du contenu de l'en-tête de requête Accept
dans presque tous les types de serveurs Web. Par exemple, vous pouvez réécrire les requêtes d'image sur les serveurs Apache en fonction de l'en-tête Accept
à l'aide de mod_rewrite
.
Ce comportement n'est pas différent de celui que vous trouverez sur un réseau de diffusion de contenu (CDN) d'images. Les CDN d'images sont d'excellentes solutions pour optimiser les images et envoyer le format optimal en fonction de l'appareil et du navigateur de l'utilisateur.
L'essentiel est de trouver un équilibre, de générer un nombre raisonnable d'images candidates et de mesurer l'impact sur l'expérience utilisateur. Différentes images peuvent donner des résultats différents, et les optimisations appliquées à chaque image dépendent de sa taille sur la page et des appareils utilisés par vos utilisateurs. Par exemple, une image héros pleine largeur peut nécessiter plus de variantes que les miniatures sur une page de fiche produit d'e-commerce.
Chargement différé
Vous pouvez demander au navigateur de charger les images de manière différée lorsqu'elles apparaissent dans le viewport à l'aide de l'attribut loading
. Une valeur d'attribut lazy
indique au navigateur de ne pas télécharger l'image tant qu'elle n'est pas dans (ou à proximité) du viewport. Cela permet d'économiser de la bande passante, ce qui permet au navigateur de hiérarchiser les ressources dont il a besoin pour afficher le contenu essentiel qui se trouve déjà dans le viewport.
decoding
L'attribut decoding
indique au navigateur comment décoder l'image. Une valeur de async
indique au navigateur que l'image peut être décodée de manière asynchrone, ce qui peut améliorer le temps d'affichage d'autres contenus. Une valeur de sync
indique au navigateur que l'image doit être présentée en même temps que d'autres contenus.
La valeur par défaut de auto
permet au navigateur de décider de ce qui est le mieux pour l'utilisateur.
Démonstrations d'images
Tester vos connaissances
Quels formats d'image sont compatibles avec la compression sans perte ?
Quels formats d'image sont compatibles avec la compression avec perte ?
Que dit le descripteur de largeur (par exemple, 1000w
) au navigateur concernant une image candidate spécifiée dans un attribut srcset
?
Que dit l'attribut sizes
au navigateur au sujet d'un élément <img>
auquel il est appliqué ?
srcset
d'un élément <img>
doit être chargé, compte tenu des dimensions du viewport actuel de l'utilisateur.
srcset
de l'élément <img>
.
Vidéo suivante: Performances des vidéos
Bien que les images soient le type de contenu multimédia le plus répandu sur le Web, elles ne sont pas le seul élément à prendre en compte en termes de performances. La vidéo est un autre type de contenu multimédia couramment utilisé sur le Web, qui présente ses propres considérations en termes de performances. Dans le module suivant de ce cours, découvrez quelques techniques d'optimisation des vidéos et de chargement efficace.