Blog home
Comment optimiser l'image LCP ?

Comment optimiser l'image LCP ?

Eloïse Martin · June 23, 2022 · 30 min read

Introduction

Le LCP, Largest Contentful Paint, une des trois métriques des Core Web Vitals récemment définis par Google pour mesurer la qualité de l’expérience utilisateur, est souvent complexe à appréhender pour les développeurs en charge de l’intégration des sites web.

Cette métrique, qui permet d’évaluer le temps que prend le navigateur à charger le contenu principal qui se trouve dans le viewport à la requête de la page, n’est en effet pas toujours évidente à optimiser. Et c’est d’autant plus vrai lorsque le Largest Contentful Paint de la page web est une image.

C’est en réponse à cette problématique que nous avons justement rédigé cet article. Vous y trouverez les bonnes pratiques et informations nécessaires à l’intégration et optimisation de votre image LCP à travers les points suivants :

  • Comment avoir recours aux attributs srcset et sizes de la balise <img> pour optimiser la métrique LCP.
  • L’usage de la balise <link> avec les attributs rel="preload" et fetchpriority="high", qui permettent d’aller encore plus loin dans l’optimisation du score LCP.

Tout au long de cet article, des explications sur le comportement des navigateurs seront données vis-à-vis de ces balises et de leurs attributs afin de vous aider à contourner les difficultés d’intégration. Nous illustrerons par ailleurs ces propos à travers des exemples et démonstrations.

Les images utilisées dans les démonstrations Codepen de cet article ont été intégrées avec TwicPics afin de gagner du temps dans leur création et accélérer l’optimisation de la métrique LCP.
Si vous souhaitez découvrir comment identifier l’élément HTML LCP sur vos pages web avant de poursuivre la lecture, consultez cet article .

Exit le lazy-loading sur l’image LCP

Lorsque nous naviguons sur internet et visitons un site web, il n’est pas rare de constater que le chargement de l’image LCP est différé via un script (lazy-loading).

Voici donc un rappel important avant d’aller plus loin : le délai induit par la technique de lazy-loading est comptabilisé dans le calcul de la métrique LCP.

Concrètement, cela signifie que si vous appliquez du lazy-loading pour gérer votre image LCP, le délai ajouté au chargement de l’image sera pénalisant pour le score LCP de votre page web.

De la même manière, le progressive loading ou le “LQIP” (Low Quality Image Placeholder) ne sont pas non plus considérés comme des optimisations par Google à l’heure où nous écrivons ces lignes. Des discussions sont cependant en cours sur ce point et la situation pourrait changer à l’avenir.

Pour cette raison, nous conseillons de laisser le navigateur charger l’image aussi tôt que possible. La métrique LCP de votre page obtiendra ainsi un score plus optimal, et votre site web aura moins de risque de subir des pénalités vis-à-vis de son référencement.

perf-optimization-1

Laisser le navigateur choisir l’image la mieux adaptée

Alors comment s’y prendre pour améliorer l’image LCP ?

Plutôt que de déclarer une unique image via l’attribut src - dont les dimensions seraient identiques pour tous les utilisateurs quel que soit leur appareil - il faut laisser le navigateur choisir l’image la mieux adaptée à chaque contexte.

let-the-browser-choose-the-image-1

Nous devons pour cela lui donner les informations dont il a besoin, via les attributs srcset et sizes de la balise <img> :

  • L’attribut srcset indique au navigateur une liste d’images et leur largeur intrinsèque.
  • L’attribut sizes renseigne quant à lui la largeur occupée par l’image, combinée éventuellement à l’usage de media queries pour adapter le choix de l’image à la largeur de l’écran.
Seule la balise <picture> permet au navigateur de charger des images différentes en fonction des caractéristiques de l'appareil (taille, résolution, orientation, etc.). Afin de simplifier l’article, nous nous appuierons uniquement sur l’usage de la balise <img> .

Balise <img> : l'attribut srcset

L’attribut srcset de la balise <img> indique donc une liste d’images et leur largeur intrinsèque : c’est dans cette liste que le navigateur va choisir l’image qui lui semble la mieux adaptée au contexte des utilisateurs.

L’attribut srcset est ainsi la première étape vers l’optimisation de votre image LCP.

<img srcset="" src="" alt="" />

Pour déclarer cette liste d’images, il est recommandé de suivre une approche mobile first : déclarez la plus petite image (l’image par défaut) au sein de l’attribut src puis déclarez-la à nouveau au sein de l’attribut srcset, suivie de ses variantes plus larges en dimensions.

mobile-first

La largeur intrinsèque de chacune des images, exprimée en pixels, doit également être indiquée via l’unité w (w pour "width") :

<img
  src="image-300.png"
  srcset="
    image-300.png 300w,
    image-900.png 900w,
    image-1800.png 1800w"
  alt="Image description"
/>

Notre exemple ci-dessus définit trois images (image-300.png, image-900.png, et image-1800.png), séparées par une virgule, et aux largeurs intrinsèques respectives de 300, 900 et 1800 pixels. Pour respecter l’approche mobile-first, image-300.png est ici l’image par défaut, définie au sein des attributs src et srcset.

Lorsque vous utilisez l’attribut srcset , il est nécessaire de conserver l’attribut src pour indiquer au navigateur l’image par défaut et assurer son affichage sur tous les navigateurs, même lorsqu’ils ne gèrent pas l'attribut srcset .
Il est également possible d’utiliser l’attribut srcset en déclarant le DPR (Device Pixel Ratio) des images plutôt que leur largeur. Cette approche ne sera pas abordée ici.

Le navigateur peut maintenant choisir et charger, en fonction du contexte de l’utilisateur, une des images déclarées au sein de l’attribut srcset.

srcset-images

Cependant le choix de l’image n’étant pas fait au hasard, il est important de comprendre les points suivants pour éviter les difficultés :

  • Au sein de l’attribut srcset, le navigateur choisit toujours l’image en référence à la taille du viewport et non en référence aux dimensions d’affichage de l’image : vos styles et media queries CSS n’ont ainsi aucun impact sur son choix, et il faudra donc aussi penser à l’orientation paysage des appareils, en particulier mobiles et tablettes, pour définir la liste des images.
  • Par défaut (sans indication de notre part) le navigateur choisit l’image en considérant toujours celle-ci comme occupant 100% de la largeur du viewport.
  • Le navigateur ayant connaissance de la résolution des appareils, il choisit également l’image en fonction du DPR : pour optimiser l’image LCP, il sera aussi nécessaire de définir une variante pour chaque DPR.

Nous pouvons comprendre de ces comportements que la formule appliquée par défaut par le navigateur pour choisir l’image est :

calculation-1
Lorsqu’il n’existe pas dans la liste une image qui fait exactement la largeur attendue par le navigateur selon sa formule de calcul, celui-ci tentera alors de trouver une autre image, à une largeur similaire. Cette image peut être la précédente ou la suivante dans la liste, selon celle qu’il estimera la mieux adaptée.

Illustrons tous ces éléments en reprenant le code précédent à travers quelques exemples et en s’appuyant sur cette démo :

<img
  src="image-300.png"
  srcset="
    image-300.png 300w,
    image-900.png 900w,
    image-1800.png 1800w" 
  alt="Image description"
/>

Tandis que dans notre démo, l’image s’affiche à 280 pixels de largeur sur tous les appareils, nous allons voir que la liste des images définies au sein de l’attribut srcset ne permet pas au navigateur de charger une image optimale, selon sa formule viewportWidth x 100% x DPR.

Rendez-vous dans les outils de développement aux onglets Network > Img pour voir l’image choisie par le navigateur selon chaque viewport et DPR.

Exemple 1

Sur un écran large de 900 pixels en DPR 1, le navigateur va chercher dans la liste des images de l’attribut srcset une image qui fait :

sample-1

Soit une image de 900 pixels.

Dans notre exemple, si les dimensions d’affichage de l’image sont de 280 pixels, c’est donc l’image aux dimensions intrinsèques de 900 pixels qui sera tout de même chargée.

screenshot-1

Exemple 2

Sur un écran large de 300 pixels en DPR 3, le navigateur va chercher une image qui fait 300 x 100% x 3, soit une image de 900 pixels.

Ici, c’est encore une fois l’image aux dimensions intrinsèques de 900 pixels qui serait chargée malgré les règles CSS qui ont été définies sur l’image et son parent.

screenshot-2

Exemple 3

Sur un écran large de 300 pixels en DPR 2, le navigateur cherche dans la liste des images de l’attribut srcset une image qui fait 300 x 100% x 2, soit une image de 600 pixels.

Mais aucune image de 600 pixels n’a été définie au sein de l’attribut srcset de notre démo.

Lorsque cette situation arrive, le navigateur identifie la largeur des images précédente et suivante, ici 300 pixels et 900 pixels, pour décider quelle image charger.

Or, quand la largeur de l’image calculée par le navigateur est la valeur médiane entre les largeurs des images précédente et suivante de l’attribut srcset, le navigateur choisit l’image de largeur supérieure.

C’est bien le cas dans notre démo puisque (300 + 900) / 2 = 600. C’est donc l’image de 900 pixels de largeur qui est encore une fois chargée.

screenshot-3

Exemple 4

Sur un écran large de 900 pixels en DPR 3, le navigateur va chercher une image qui fait 900 x 100% x 3, soit une image de 2700 pixels.

Comme aucune image de 2700 pixels n’a été déclarée dans la liste des images et qu’aucune image de largeur supérieure n’existe, le navigateur chargera alors la dernière image de 1800 pixels définie au sein de la liste.

screenshot-4

Ces exemples nous confirment que les images déclarées au sein de l’attribut srcset ne sont pas adaptées à la largeur d’affichage de 280 pixels sur tous les appareils.

Alors que le navigateur applique la formule viewportWidth x 100% x DPR pour connaître l’image à charger, la formule à appliquer de notre côté pour connaître et créer les différentes images à déclarer au sein de l’attribut srcset est plus simple :

calculation-2

Ainsi, en tenant compte des DPRs 1, 2, et 3 sur notre première démo, il nous faudrait créer et définir les trois images suivantes :

  • DPR 1 : 280 x 1 => une image à 280 pixels de largeur
  • DPR 2 : 280 x 2 => une image à 560 pixels de largeur
  • DPR 3 : 280 x 3 => une image à 840 pixels de largeur

Et adapter enfin notre code (👉 voir nouvelle démo) :

<img
  src="image-280.png"
  srcset="
    image-280.png 280w,
    image-560.png 560w,
    image-840.png 840w" 
  alt="Image description"
/>

Mais le code de notre nouvelle démo n’est pas encore complètement adapté à tous les appareils.

En effet, dans le cas d’un appareil de type laptop dont le viewport est de 1024 pixels et en DPR 2, le navigateur souhaitera charger une image de 1024 x 100% x 2, soit une image de 2048 pixels, qui n’existe pas au sein de l’attribut srcset.

Nous nous retrouvons dans une situation similaire à l’exemple 4 précédent, où le navigateur va charger la dernière image de la liste de l’attribut srcset : c’est l’image de 840 pixels qui sera chargée alors que l’image optimale devrait être d’une largeur intrinsèque de 560 pixels sur ce laptop en DPR 2 (imageRenderedSize x DPR = 280 x 2 = 560).

Découvrons maintenant l’attribut sizes, qui va justement nous permettre de contrôler ce comportement du navigateur.

Balise <img> : l’attribut sizes

L’attribut sizes permet de contrôler le comportement du navigateur pour éviter qu’il ne considère l’image comme occupant 100% du viewport par défaut sur tous les appareils, et d’assurer ainsi le chargement d’une image optimale.

<img srcset="" sizes="" src="" alt="" />
L’attribut sizes n’est donc pas nécessaire lorsque l’image occupe 100% du viewport en toutes circonstances.

Pour assigner la valeur de l’attribut sizes, il est possible d’utiliser et mixer les approches suivantes :

  • Définir la largeur de l’image en pourcentage, en référence à la largeur du viewport, lorsque l’image est responsive (propriété CSS width définie en pourcentage par exemple).
  • Définir la largeur de l’image en pixels, lorsque celle-ci a une largeur d’affichage fixe quels que soient les appareils des utilisateurs.
  • Utiliser une ou plusieurs media queries pour permettre au navigateur de faire le meilleur choix d’image selon différents types de viewports.

Appuyons-nous cette fois sur cette démo et sur le code suivant pour illustrer nos propos :

<img
  src="image-280.png"
  srcset="
    image-280.png 280w,
    image-480.png 480w,
    image-560.png 560w,
    image-840.png 840w,
    image-960.png 960w,
    image-1440.png 1440w" 
  sizes="(min-width: 768px) 480px, 87.5vw"
  alt="Image description"
/>

Largeur en pourcentage du viewport

Pour connaître la largeur du viewport occupée par l’image en pourcentage, il faut appliquer la formule suivante :

calculation-3

En consultant la démo sur un mobile au viewport de 320 pixels, nous pouvons voir depuis les outils de développement que l’image s’affiche à une largeur de 280 pixels.

screenshot-5

Selon la formule (imageRenderedSize / viewportWidth) x 100%, l’image occupe donc (280 / 320) x 100% = 87.5% de la largeur du viewport (87.5vw) :

<img srcset="" sizes="87.5vw" src="" alt="" />

Le navigateur sait maintenant que l’image doit occuper 87.5% de la largeur du viewport, et non plus 100% par défaut. La formule précédemment appliquée par défaut par le navigateur pour choisir l’image :

viewportWidth x 100% x DPR

Devient donc :

viewportWidth x 87.5% x DPR

Si nous considérons les DPRs 1, 2, et 3, toujours sur ce mobile au viewport de 320 pixels, le navigateur va donc chercher à charger les trois images suivantes :

  • DPR 1 : 320 x 87.5% x 1 => image à 280 pixels
  • DPR 2 : 320 x 87.5% x 2 => image à 560 pixels
  • DPR 3 : 320 x 87.5% x 3 => image à 840 pixels

Ce qui correspond exactement aux images que nous avions définies plus tôt via la formule imageRenderedSize x DPR dans le code suivant :

<img
  src="image-280.png"
  srcset="
    image-280.png 280w,
    image-560.png 560w,
    image-840.png 840w" 
  alt="Image description"
/>

Que nous pouvons maintenant adapter avec l’attribut sizes="87.5vw" :

<img
  src="image-280.png"
  srcset="
    image-280.png 280w,
    image-560.png 560w,
    image-840.png 840w" 
  sizes="87.5vw"
  alt="Image description"
/>

Avec ce code, le navigateur est dorénavant capable de choisir l’image parfaite dans le contexte de :

  • Notre mobile au viewport de 320 pixels en orientation portrait
  • La largeur d’affichage de l’image de 280 pixels (= 87.5% du viewport de 320 pixels)
  • Chaque DPR (1, 2 et 3)

Largeur en pixels

Toujours dans notre démo, nous pouvons voir que l’image s’affiche à 480 pixels sur tous les appareils dont le viewport est cette fois d’au moins 768 pixels.

screenshot-6

Au sein de l’attribut srcset, les images à prévoir pour tous ces appareils selon la formule imageRenderedSize x DPR pour les DPRs 1, 2 et 3 sont donc :

  • DPR 1 : 480 x 1 => une image à 480 pixels de largeur
  • DPR 2 : 480 x 2 => une image à 960 pixels de largeur
  • DPR 3 : 480 x 3 => une image à 1440 pixels de largeur
<img
  src="image-480.png"
  srcset="
    image-280.png 280w,
    image-480.png 480w,
    image-560.png 560w,
    image-840.png 840w,
    image-960.png 960w,
    image-1440.png 1440w"
  sizes="87.5vw"
  alt="Image description"
/>

Mais si nous considérons le cas spécifique d’une tablette au viewport de 768 pixels, l’image n’occupe non plus 87.5% de la largeur du viewport mais 62.5%, selon la formule (imageRenderedSize / viewportWidth) x 100% :

(480 / 768) x 100% = 62.5%

Pour distinguer nos deux viewports de 320 pixels et 768 pixels, nous pouvons dans un premier temps adapter l’attribut sizes à l’aide d’une media query :

sizes="(width: 768px) 62.5vw, 87.5vw"

Mais ce que nous souhaitons réellement, c’est indiquer au navigateur que l’image occupe une largeur fixe de 480 pixels quels que soient les appareils dont le viewport est d’au moins 768 pixels. Il est donc requis ici de définir la largeur en pixels plutôt qu’en pourcentage du viewport, et d’adapter notre media-query :

sizes="(min-width: 768px) 480px, 87.5vw"

Comme nous l’avons mentionné plus tôt, il est possible de définir plusieurs media queries au sein de l’attribut sizes. La dernière valeur de l’attribut sizes, sans media query (ici 87.5vw), sera considérée par le navigateur comme la valeur par défaut lorsqu’aucune des conditions posées par les media queries n’est respectée.
<img
  src="image-280.png"
  srcset="
    image-280.png 280w,
    image-480.png 480w,
    image-560.png 560w,
    image-840.png 840w,
    image-960.png 960w,
    image-1440.png 1440w" 
  sizes="(min-width: 768px) 480px, 87.5vw"
  alt="Image description"
/>

Dorénavant avec le code source de notre démo, et quel que soit le DPR, le navigateur peut charger l’image parfaite :

  1. Pour la largeur d’affichage de 280 pixels sur un mobile au viewport de 320 pixels en orientation portrait
  2. Et pour la largeur d’affichage de 480 pixels sur tous les appareils dont le viewport est d’au moins 768 pixels

C’est ainsi que la combinaison des attributs srcset et sizes permet une optimisation presque parfaite de la métrique LCP.

Si nous parlons d’optimisation “presque parfaite”, c’est qu’il est possible à cette étape d’aller encore plus loin dans l’optimisation de la métrique LCP grâce à la balise <link rel="preload">.

Présentation

Sur la balise <link>, la valeur preload de l’attribut rel permet de déclarer les ressources de la page qui nécessitent d’être chargées le plus tôt possible, avant même que le navigateur n’enclenche sa phase de rendu.

Cette technique de pré-chargement permet à une ressource d’être déjà disponible au moment où le navigateur ne découvre la ligne du code source qui en fait la requête. Elle diminue donc les délais dans le rendu de la page dûs au chargement d’une ressource, et améliore ses performances.

Alors qu’il est possible de faire du pré-chargement avec tous types de ressource (CSS, JavaScript, images, …), la balise <link rel="preload"> est d’autant plus pertinente concernant l'image LCP : en compagnie des attributs srcset et sizes de la balise <img>, c’est le trio gagnant pour une optimisation parfaite de la métrique LCP de votre page web.

Afin d’illustrer les propos qui arrivent, appuyons nous sur cette démo et sur le code suivant :

<head>
  <!-- 1. pour les mobiles au viewport de 320 pixels -->
  <link
    rel="preload" as="image" href="image-280.png"
    media="(width: 320px)"
    imagesrcset="
      image-280.png 280w, 
      image-560.png 560w,
      image-840.png 840w"
    imagesizes="87.5vw">

  <!-- 2. pour les appareils au viewport d'au moins 768 pixels -->
  <link
    rel="preload" as="image" href="image-480.png"
    media="(min-width: 768px)"
    imagesrcset="
      image-480.png 480w,
      image-960.png 960w,
      image-1440.png 1440w"
    imagesizes="480px">
</head>

<body>
  <img src="image-280.png"
    srcset="
      image-280.png 280w,
      image-480.png 480w,
      image-560.png 560w,
      image-840.png 840w,
      image-960.png 960w,
      image-1440.png 1440w"
    sizes="(min-width: 768px) 480px, 87.5vw"
    alt="Image description"
  />
</body>
Le code donné ci-dessus étant relativement court, le gain sur la métrique LCP sera sans doute négligeable. Mais dans un code source avec plusieurs centaines de lignes qui séparent la balise <link> de sa balise <img> correspondante, le pré-chargement de votre image peut avoir un réel impact sur le score LCP de votre site web !
Pour consulter les balises <link> définies au sein de la démo , rendez-vous dans les onglets Settings > HTML > Stuff for <head> .
screenshot-7
screenshot-8

Intégration

Pour pouvoir pré-charger une image à l’aide de la balise <link rel="preload">, deux attributs sont requis en toutes circonstances : les attributs as et href.

L’attribut as permet de spécifier le type de la ressource, une image dans notre cas.

L’attribut href renseigne quant à lui l’image par défaut :

<link rel="preload" as="image" href="default-image.png">

Mais lorsque la balise <link rel="preload"> est utilisée pour pré-charger l’image LCP, dont plusieurs variantes ont été déclarées au sein de l’attribut srcset de la balise <img>, l’intégration est plus complexe que lorsqu’une unique image a été définie via un simple attribut src.

Ainsi, pour permettre au navigateur de pré-charger la bonne image LCP, c’est-à-dire celle qui devrait normalement être chargée à la découverte de la balise <img>, d’autres attributs de la balise <link> sont nécessaires :

  • Attribut media
  • Attribut imagesrcset
  • Attribut imagesizes

Attribut media

L’attribut media permet de définir une media query qui indique au navigateur si la balise <link> doit être ou non prise en compte selon certaines conditions.

Comme c’est le cas depuis le début de cet article, l’image LCP n’est toujours optimisée que pour deux types d’appareils dans notre démo :

  1. Les appareils de type mobile au viewport de 320 pixels
  2. Tous les appareils dont le viewport est d’au moins 768 pixels

Nous avons donc besoin de deux balises <link>, dont l’attribut media doit définir une condition relative à la largeur du viewport de nos deux types d’appareil. Cela permet au navigateur de décider à quel contexte s’applique chacune des balises <link> :

<head>
  <!-- 1. pour les mobiles au viewport de 320 pixels -->
  <link
    rel="preload" as="image" href="image-280.png"
    media="(width: 320px)"
  >
  <!-- 2. pour les appareils au viewport d'au moins 768 pixels -->
  <link
    rel="preload" as="image" href="image-480.png"
    media="(min-width: 768px)"
  >
</head>

<body>
  <img
    src="image-280.png"
    srcset="
      image-280.png 280w,
      image-480.png 480w,
      image-560.png 560w,
      image-840.png 840w,
      image-960.png 960w,
      image-1440.png 1440w" 
    sizes="(min-width: 768px) 480px, 87.5vw"
    alt="Image description"
  />
</body>

Grâce à la définition des attributs media, le navigateur appliquera désormais la première balise <link> uniquement pour les mobiles au viewport de 320 pixels (media="width: 320px"), tandis que la deuxième balise <link> ne sera prise en compte que pour les appareils dont le viewport est d’au moins 768 pixels (media="min-width: 768px").

Cet attribut media est donc indispensable pour éviter de précharger des images inutiles, qui ne seront finalement jamais affichées pour un contexte donné.

Attribut imagesrcset

Des deux balises <link> que nous venons d’ajouter, nous comprenons que la liste des images déclarées plus tôt au sein de l’attribut srcset de la balise <img> doit être découpée en deux :

  1. La liste des images pour les mobiles au viewport de 320 pixels
  2. La liste des images pour tous les appareils dont le viewport est d’au moins 768 pixels

Et c’est justement l’attribut imagesrcset de la balise <link> qui doit recevoir chacune de ces listes :

<head>
  <!-- 1. pour les mobiles au viewport de 320 pixels -->
  <link
    rel="preload" as="image" href="image-280.png"
    media="(width: 320px)"
    imagesrcset="
      image-280.png 280w,
      image-560.png 560w,
      image-840.png 840w"
  >
  <!-- 2. pour les appareils au viewport d'au moins 768 pixels -->
  <link
    rel="preload" as="image" href="image-480.png"
    media="(min-width: 768px)"
    imagesrcset="
      image-480.png 480w,
      image-960.png 960w,
      image-1440.png 1440w"
  >
</head>

<body>
  <img
    src="image-280.png"
    srcset="
      image-280.png 280w,
      image-480.png 480w,
      image-560.png 560w,
      image-840.png 840w,
      image-960.png 960w,
      image-1440.png 1440w" 
    sizes="(min-width: 768px) 480px, 87.5vw"
    alt="Image description"
  />
</body>

Nous y sommes presque, mais notre code ci-dessus nécessite encore d’être adapté.

En effet, pour faire le choix de l’image à précharger au sein de l’attribut imagesrcset de la balise <link>, le navigateur considère ici encore que l’image occupe par défaut 100% de la largeur du viewport.

Ainsi, si nous consultons cette démo sur un appareil au viewport de 768 pixels en DPR 1, nous pouvons voir dans les outils de développement que deux images sont chargées :

  • Une première image de 960 pixels, qui correspond à l’image pré-chargée via la balise <link>. C’est normal car le navigateur a appliqué ici sa formule viewportWidth x 100% x DPR pour définir l’image à pré-charger, et souhaitait donc une image de 768 pixels (768 x 100% x 1). Mais aucune image de 768 pixels n’a été définie au sein de l’attribut imagesrcset de la balise <link> : le navigateur s’est donc reporté sur l’image de 960 pixels.
  • Une deuxième image de 480 pixels, chargée cette fois via la balise <img>, selon le comportement du navigateur que nous avons pu voir plus tôt vis-à-vis de ses attributs srcset et sizes.
screenshot-9
Cet exemple nous démontre qu’il faut être vigilant lorsque la balise <link> est utilisée pour pré-charger l’image LCP : dans les outils de développement aux onglets Network > Image , il est conseillé de toujours bien vérifier pour chaque largeur de viewport que l’image affichée via la balise <img> correspond bien à l’image qui a été chargée via la balise <link> .

Afin de contrôler le comportement par défaut du navigateur pour choisir l’image à pré-charger via la balise <link>, c’est cette fois l’attribut imagesizes qui nous est utile.

Attribut imagesizes

L’attribut imagesizes de la balise <link> fonctionne exactement comme l’attribut sizes de la balise <img>, à une exception près :

  • Contrairement à l’attribut sizes de la balise <img>, l’attribut imagesizes n’accepte pas de media query puisque, tel que nous l’avons vu, c’est l’attribut media de la balise <link> qui doit définir celle-ci.
  • L’attribut imagesizes ne peut donc accepter qu’une seule valeur, correspondant à la largeur d’affichage occupée par l’image. Comme pour l’attribut sizes, celle-ci peut être définie :
    • en pourcentage de la largeur du viewport lorsque l’image est responsive (e.g. : imagesizes="50vw").
    • ou prendre une valeur en pixels lorsque l’image possède une largeur fixe (e.g. : imagesizes="1200px").

Le code peut maintenant être adapté :

<head>
  <!-- 1. pour les mobiles au viewport de 320 pixels -->
  <link
    rel="preload" as="image" href="image-280.png"
    media="(width: 320px)"
    imagesrcset="
      image-280.png 280w,
      image-560.png 560w,
      image-840.png 840w"
    imagesizes="87.5vw"
  >
  <!-- 2. pour les appareils au viewport d'au moins 768 pixels -->
  <link
    rel="preload" as="image" href="image-480.png"
    media="(min-width: 768px)"
    imagesrcset="
      image-480.png 480w,
      image-960.png 960w,
      image-1440.png 1440w"
    imagesizes="480px"
  >
</head>

<body>
  <img
    src="image-280.png"
    srcset="
      image-280.png 280w,
      image-480.png 480w,
      image-560.png 560w,
      image-840.png 840w,
      image-960.png 960w,
      image-1440.png 1440w" 
    sizes="(min-width: 768px) 480px, 87.5vw"
    alt="Image description"
  />
</body>

Dans notre démo, le navigateur peut dorénavant, via nos deux balises <link> et leurs différents attributs, connaître à l’avance l’image optimale requise et la pré-charger pour les appareils au viewport de 320 pixels et pour les appareils au viewport d’au moins 768 pixels.

Voyons pour terminer cet article l'attribut fetchpriority.

Attribut fetchpriority

Pour gérer les ressources d’une page, le navigateur applique nativement un ordre de chargement selon une priorité définie, entre autres paramètres, par le type de la ressource.

Bien que la logique de priorisation du navigateur puisse être satisfaisante la plupart du temps, il peut être judicieux de manipuler son comportement par défaut pour qu’il considère l’image LCP comme prioritaire par rapport à d’autres ressources.

C’est l’attribut fetchpriority="high" qui nous permet de modifier cette priorité de traitement du chargement.

Les valeurs possibles de l’attribut fetchpriority sont high , low et auto .

Puisque l’attribut fetchpriority est complémentaire de la technique de pré-chargement que nous avons implémentée pour optimiser la métrique LCP, c’est sur les balises <link> que nous devons le définir, tel que démontré dans cette démo finale :

<head>
  <!-- 1. pour les mobiles au viewport de 320 pixels -->
  <link
    rel="preload" as="image" fetchpriority="high" href="image-280.png"
    media="(width: 320px)"
    imagesrcset="
      image-280.png 280w,
      image-560.png 560w,
      image-840.png 840w"
    imagesizes="87.5vw"
  >
  <!-- 2. pour les appareils au viewport d'au moins 768 pixels -->
  <link
    rel="preload" as="image" fetchpriority="high" href="image-480.png"
    media="(min-width: 768px)"
    imagesrcset="
      image-480.png 480w,
      image-960.png 960w,
      image-1440.png 1440w"
    imagesizes="480px"
  >
</head>

<body>
  <img
    src="image-280.png"
    srcset="
      image-280.png 280w,
      image-480.png 480w,
      image-560.png 560w,
      image-840.png 840w,
      image-960.png 960w,
      image-1440.png 1440w" 
    sizes="(min-width: 768px) 480px, 87.5vw"
    alt="Image description"
  />
</body>
L’attribut fetchpriority est compatible avec les versions Chrome 101 et au-delà.

Nous avons finalement abordé tous les points pour vous permettre non seulement d’optimiser votre image LCP selon chaque contexte, mais aussi de prioriser son chargement par rapport à d’autres ressources.

L’optimisation de l’image LCP ne devrait dorénavant plus avoir de secret pour vous ! 🙂

En résumé

En guise de conclusion, voici un récapitulatif des étapes requises à l’optimisation de votre image LCP et explicitées au cours de cet article :

  1. Dès que le template de page de votre site web a été défini, créez et stockez toutes les images nécessaires à chaque appareil et à chaque DPR selon la formule imageRenderedSize x DPR. Vous pouvez aussi utiliser directement l’API de TwicPics pour passer cette étape.

  2. Utilisez la balise <img> pour intégrer la liste des images définies dans l’étape 1 via son attribut srcset, en suivant une approche mobile-first (sans oublier l’image par défaut au sein de l’attribut src).

  3. Grâce à l’attribut sizes de la balise <img>, et si besoin à l’aide de media queries, indiquez au navigateur tous les appareils pour lesquels les dimensions d’affichage de l'image changent, en renseignant la largeur occupée par l’image :

  • Si l’image est responsive, définissez sa largeur en pourcentage de la largeur du viewport via la formule (imageRenderedSize / viewportWidth) x 100%.
  • Si l’image est fixe entre un ou plusieurs appareils, définissez simplement sa largeur en pixels.
  1. Pour améliorer encore votre métrique LCP, utiliser une balise <link rel="preload" as="image" href="default-image.png"> pour chaque media query qui a été définie au sein de l’attribut sizes de la balise <img> (valeur par défaut comprise).

  2. Enfin, utiliser l’attribut fetchpriority="high" sur chaque balise <link> mentionnée à l’étape 4 pour prioriser le chargement de votre image LCP par rapport à d’autres ressources.