Les Core Web Vitals feront partie des critères de classement de l’algorithme de Google dès le mois de mai 2021 (mise à jour « Google Page expérience » avec des critères orientés UX). Bien que cet update n’aura probablement pas un impact majeur sur les positions, ces métriques méritent une attention particulière, ne serait-ce que pour soigner l’expérience utilisateur. Après avoir passé en revue le LCP (Largest Contentful Paint) dans notre article du mois dernier, nous allons aborder aujourd'hui un autre KPI des Core Web Vitals, à savoir le CLS : Cumulative Layout Shift.

 

L'indicateur CLS n’est pas relatif au temps de chargement initial de la page comme le LCP, mais plutôt à l’impact que peuvent avoir les différents mouvements des éléments dans une page sur l’UX. Nous allons décrypter dans cet article comment ce KPI fonctionne, sa méthode de calcul, ainsi que les optimisations possibles pour l’améliorer, sans oublier les différents outils pour identifier les éléments qui peuvent nuire à un bon CLS.

Principe du CLS

Le CLS est une métrique orientée utilisateur qui mesure l’ensemble des mouvements qui peuvent intervenir pendant la durée de vie d’une page. Chaque changement de position est mesuré via une formule que nous allons détailler, et la somme de toutes ces mesures indique le CLS global de la page. Un Bon CLS doit être inférieur à 0,1.

Figure 1 - Echelle de mesure du score CLS

 

Il n’est pas rare d’avoir un contenu affiché à l’écran et que ce dernier se décale subitement, horizontalement ou verticalement, à la suite de l’apparition d’une publicité (ou d’une image par exemple). La mesure de la stabilité visuelle d’une page via le CLS a pour objectif de limiter les mauvaises expériences sur une page, en permettant aux utilisateurs de pouvoir parcourir les contenus d’un site, sans que certains éléments inattendus décalent le contenu. Un mauvais CLS pourrait ainsi dégrader la navigation de l’internaute, et augmenter le taux de rebond. Voici un exemple :

Figure 2 - Augmentation du CLS à cause de publicités - Source : https://nicj.net/

 

Le décalage des éléments dans une page peut également amener les utilisateurs à cliquer sur un mauvais élément par rapport à leur intention initiale, comme le présente cet autre exemple :

Figure 3 - Clic sur un élément non souhaité

 

Pour mieux comprendre comment réduire le CLS des pages d’un site, il est nécessaire de bien comprendre comme ce dernier se calcule.

 

Méthode de calcul du CLS

Le CLS est calculé en additionnant tous les changements de disposition qui ne sont pas causés par l'interaction de l'utilisateur. Un utilisateur qui ouvrira un texte dépliable par exemple provoquera un Layout Shift, mais qui ne sera pas intégré dans le calcul puisqu’il aura été généré par une action de l’utilisateur.

En effet, les déplacements provoqués à la suite d’un clic d’un utilisateur ne seront pas intégrés dans le calcul, et ce sur un délai de 500ms. Par exemple, si un utilisateur clique sur un bouton pour afficher un texte qui était rétracté, un décalage se produit. C’est seulement si ce décalage intervient plus de 500ms après le clic d’un utilisateur qu’il sera intégré dans le calcul du CLS :

Figure 4 - Déplacement non comptabilisés après une action utilisateur

 

Cependant, les carrousels avec défilements automatiques peuvent provoquer des déplacements d’éléments, qui pourront faire augmenter le CLS, d’autant plus si l’utilisateur reste longtemps sur la page. Afin d’éviter que ce type de déplacements (propres à la structure de certaines pages) soient comptabilisés, les éléments qui se déplacent via la propriété CSS transform (ex :  transition : transform .5s) ne seront pas pris en compte dans le calcul final du CLS :

  • Utiliser transform : (scale) plutôt que de modifier les propriétés width et height ;
  • En cas de déplacement d’éléments, ne pas modifier les propriétés de positionnement (top, bottom, left, right) mais préférer l’utilisation de transform : translate().

La mesure du CLS ne prend donc pas en compte certains changements qui pourraient fausser les résultats, et a été plutôt bien pensée. Pour mieux comprendre ce qu’est le CLS et la façon dont il est calculé, il faut mesurer la proportion de la fenêtre d'affichage qui a été touchée par les changements de disposition, et la distance de déplacement des éléments qui ont été déplacés.

Deux facteurs entrent en ligne de compte: l’Impact Fraction et l’Impact Distance.

 

Impact Fraction

Pour calculer l’Impact Fraction, il faudra au préalable calculer la région d'impact (Impact Region).

La région d'impact définit la zone affectée par le décalage de la mise en page. Google identifie tous les éléments concernés et combine la zone d'origine avec la version décalée, définissant ainsi la région d'impact. La région d'impact est généralement un rectangle, mais si plusieurs décalages de mise en page (horizontalement et verticalement) se produisent, il peut s'agir d'une forme plus complexe.

Pour définir l’Impact Fraction, il faut diviser la surface de la région d'impact par la surface de la fenêtre d'affichage (appelé viewport : partie de la page visible à l'écran) :

Zone de la région d'impact / Zone de la fenêtre d'affichage = Fraction d'impact

Figure 5 - Impact Fraction

 

Dans l’image ci-dessus par exemple (figure 5), le paragraphe représente la moitié du viewport soit 50% (viewport = dimension de la fenêtre d’affichage), et il se décale de 25% vers le bas. Le rectangle qui englobe l’élément décalé, ainsi que le décalage provoqué de 25%, représente 75% du viewport. On aura pour cet élément un Impact Fraction de 75/100 = 0.75.

La première version du calcul du CLS ne comprenait que l’Impact Fraction. Cependant, les grands éléments peuvent ne bouger que légèrement, et les grands mouvements sont plus gênants que les petits. Dans cette optique, le calcul du CLS a été amélioré avec l’utilisation de la mesure « distance Fraction ».

 

Distance fraction

Pour calculer la « Distance Fraction », il faut préalablement calculer la distance de déplacement.

La distance de déplacement définit la distance avant et après le déplacement de la mise en page, à savoir de combien l'élément déplacé s’est déplacé (horizontalement ou verticalement). Pour calculer la Distance Fraction, il faut diviser la distance de déplacement maximale par la surface de la fenêtre d'affichage :

Distance de déplacement maximale / Zone d’affichage la fenêtre = Distance fraction

Figure 6 - Distance Fraction

Toujours avec le même exemple, on constate que la distance de déplacement du paragraphe est de 25% par rapport à la taille horizontale de la fenêtre d’affichage du viewport, soit : 25/100 = 0.25

On aura donc pour cet exemple un Layout Shift de 0.75 x 0,25 (Impact Fraction x Distance Fraction) soit 0,1875.

Vision cumulative sur la durée de vie de la page

Le calcul du CLS d’une page consiste tout simplement à additionner l’ensemble des déplacements dans la page (Layout Shift). Le CLS se mesure pendant toute la durée de vie de la page :  en effet, les utilisateurs ont souvent une mauvaise expérience avec des Layout Shift après le chargement, lors du défilement (scroll) par exemple et de la navigation au sein des pages.  C'est pour cela que tous les déplacements d'éléments après le chargement de la page sont intégrés dans le CLS.

Cependant, les longues pages ainsi que les SPA (Single Page Application) sont plus sujettes à avoir de nombreux CLS, et donc à avoir des scores de CLS plus importants en fonction de la navigation des internautes dans ces pages. C'est pour cela qu'après avoir agrégé de nombreuses données, l'équipe Chrome Speed Metrics a décidé d'améliorer la mesure du CLS, afin que ce KPI soit le plus neutre possible par rapport au temps passé sur une page. La nouvelle méthode de calcul n'est pas encore implémentée dans les différents outils mais le sera sous peu. (plus d’informations à ce sujet ici : https://web.dev/evolving-cls/).

 

Comment améliorer le CLS ?

La majeure partie des problématiques provoquant des déplacements pourront être corrigées en adaptant l’intégration HTML / CSS des éléments concernés.

Voici les principaux facteurs provoquant une augmentation du CLS :

  • L’affichage de médias sans dimensions : image, video, etc. ;
  • Le chargement des polices (FOIT & FOUT : Flash of Invisible Text et Flash of Unstyled Text) ;
  • L’affichage de contenu sans CSS (FOUC : Flash of unstyled content) ;
  • Les annonces publicitaires ;
  • L’injection de contenu.

A noter que l'A/B testing peut également être la source de CLS, celui ci pouvant modifier des éléments dans la page à posteriori.

Affichage de médias sans dimensions

Pour mieux comprendre l’importance de dimensionner ses images, il est préférable de connaitre le fonctionnement de base d’un navigateur.

La première phase de « parsing » consiste à construire le DOM (Document Object Model) relatif à l’arborescence du HTML, ainsi que le CSSOM (CSS Object Model) décrivant les propriétés de chaque élément. Le navigateur crée ensuite l’arbre de rendu (combinaison du DOM et CSSOM) qui lui permettra de disposer les différents éléments sur la page avec la phase de « layout » (taille et position exacte de chaque élément) . Enfin, le painting est possible : le navigateur effectue la peinture des différents éléments à afficher (sous la forme de pixels) en se référant aux différentes propriétés de chaque bloc pour les placer en fonction de l’arbre de rendu.

Chemin critique de rendu

Source : https://www.artwai.com/

Dans le cas où les dimensions d’une image ne seraient pas spécifiées, le navigateur devra calculer la taille des images avant de les afficher, et donc aucun espace relatif aux dimensions de l’image ne sera réservé lors de la phase de layout : cela provoquera un déplacement des éléments dans la page lors du painting.

Afin d’éviter ce déplacement, il est indispensable de spécifier la dimension des images, ce qui permettra aux navigateurs de réserver un espace spécifique pour ces dernières (pendant la phase de layout) : aucun layout shifting ne sera donc généré. Ex :

<img src="photo-foret.jpg" width="640" height="360" alt="Bois de Saint-Cucufa" />

Avec ce type de dimensions fixes (pixels), un problème se pose pour les images responsives. En effet, l’intégration d’images occupant une partie spécifique de l’écran (en pourcentage) fait plutôt appel à ce type de propriété CSS :

img {width: 100%; /* or max-width: 100%; */ height: auto;}

Cette surface n’étant pas la même en fonction des appareils, le navigateur doit adapter la position des éléments autour des images, ce qui provoque des déplacements. Afin de palier cette problématique, le « CSS Working Group » a introduit une nouvelle propriété basée sur l’aspect ratio des images, en fonction de ses attributs width et height :

img {aspect-ratio: attr(width) / attr(height);}

Une image ayant les propriétés width="640" et height="360" a donc un aspect ration de 16/9. En spécifiant les dimensions width et height des éléments <img>, il est donc possible de connaitre l’espace que sera occupé à l’écran pour une image qui occuperait toute la largeur de l’écran.

Pour prendre un exemple, si on imagine un viewport avec une largeur de 640 px, et une image ayant la propriété suivante : img {width: 80%;}, on peut donc en déduire que la largeur qu’occupera l’image à l’écran sera de 512 px. Etant donné que cette image a un aspect ratio de 16/9, la hauteur nécessaire à l’image sera donc de 288 px. Une zone de 512 px de largeur par 288 px de hauteur sera donc réservée à l’élément <img>, afin de ne pas causer de déplacement d’autres éléments lors de son chargement.

 

Chargement des polices

Pour un site qui utilise des polices externes, elles peuvent être la cause de FOIT (Flash Of Invisible Text) et de FOUT (Flash Of Unstyled Text). Une image vaut mieux que des mots pour bien comprendre ce qui se cache derrière ces appellations :

Figure 7 - FOUT et FOIT (source: fasterize.com)

 

Quand un navigateur doit charger des polices depuis un serveur, le texte ne s’affichera pas tant que la police n’aura pas été téléchargée (FOIT), ce qui provoquera potentiellement des déplacements indésirables.

Il est possible d’utiliser une solution de fallback pour afficher malgré tout le texte avec une police par défaut, le temps que la police externe soit chargée. Cela est possible via la propriété CSS font-display qui peut avoir plusieurs valeurs (swap, fallback, optinal, etc.). Cette implémentation peut provoquer un FOUT, la police par défaut pouvant avoir des propriétés bien différentes que la police à charger :

Figure 8 - FOUT

 

Afin de limiter au maximum le CLS provoqué par ce « Flash Of Unstyled Text », il est recommandé d’utiliser une police par défaut (fallback) relativement proche. Cet outil permettra de trouver la meilleure équivalence : https://meowni.ca/font-style-matcher/

La valeur « font-display :  optional » permettra quant à elle de limiter le CLS, puisque le navigateur utilisera la police de fallback lors du premier chargement, la police externe quant à elle ne sera affichée qu’une fois qu’elle aura été mise en cache par le navigateur.

 

L’affichage de contenu sans CSS

Pour accélérer le chargement des pages, on plaçait autrefois les feuilles de style CSS en bas du code HTML pour ne pas bloquer le rendu de la page. Ce type d’intégration n’est plus optimale aujourd’hui avec l’évolution du web, et provoque un FOUC (Flash Of Unstyled Content) :

Figure 9 - FOUC

 

Ce FOUC génère des déplacements : dans l’exemple ci-dessus, les liens du menu ne sont pas intégrés dans le burger-menu (géré via CSS), ce qui crée un décalage une fois que les styles sont chargés. Les propriétés des autres éléments (positions, marges, polices, etc.) augmentent également ce layout shift.

Il est recommandé de charger en priorité les CSS, avant le contenu, pour permettre un affichage direct des éléments à leur position finale.  Des optimisations spécifiques peuvent être effectuées afin de charger en priorité les styles relatifs aux éléments situés au-dessus de la ligne de flottaison,  les contenus chargés à l’extérieur du viewport n’ayant pas d’impact sur le CLS.

 

Les annonces publicitaires

La publicité est l’un des principaux facteurs provoquant des déplacements lors de la mise en page sur les navigateurs. Les aspects dynamiques (régies pub, enchères, re-targeting, etc) et les formats multiples qui en découlent dégradent l’expérience utilisateur, et mènent parfois à des clics non souhaités, comme dans cet exemple en vidéo :

 

La principale recommandation pour éviter ces désagréments est de réserver suffisamment d’espace pour les annonces publicitaires (ex : utiliser une position:fixed ;  via les CSS pour l’élément intégrant la publicité). Par ailleurs, il est toujours utile de prévoir une petite marge supplémentaire pour éviter de légers décalages (provoqués par les paddings sur les pubs par exemple). En fixant la hauteur des containeurs de publicité, on limitera le layout shift provoqué par les publicités elles-mêmes.

 

L’injection de contenu

Par principe, le contenu injecté dynamiquement ne doit jamais apparaître au-dessus d'un contenu déjà chargé. La seule exception à cette règle est lorsque le changement est causé par une interaction avec l'utilisateur :  tant que le contenu est chargé moins de 500 ms après l'interaction, cela n’augmentera pas le CLS. Attention cependant au chargement de ressources externes à la suite d’une action utilisateur : un appel d’élément externe (requête serveur) ayant un temps de réponse trop élevé et un poids de fichier pouvant être conséquent, mènera à un chargement de plus de 500 ms après l’action de l’utilisateur, et générera donc du layout shift.

 

Comment suivre le CLS

Différents outils ont été passés en revue dans l’article suivant https://www.reacteur.com/2021/02/core-web-vitals-point-detape-et-outils-de-mesure.html, mais il est possible d’aller plus loin pour le CLS.

Dans les outils fournis via Chrome Dev Tools, il est possible d’avoir un aperçu des décalages générés pendant le chargement d’une page via l’onglet « Performance » :

Figure 10 -  Layout Shifts (LS) dans Chrome

 

Un clic sur chaque occurrence de la timeline permettra d’identifier les éléments générant des décalages. On peut également visualiser à quels moments précis interviennent les LS via la ligne dédié aux Core Web Vitals (il aura fallu cocher au préalable l’option « Core Web Vitals » visible en haut à droite de la capture ci-dessus).

La limite de ces mesures est qu’elles n’interviennent que pendant le chargement de la page. Hors le CLS mesure les déplacements d’éléments pendant toute la durée d’une vie d’une page. Pour aller plus loin et découvrir les éléments qui peuvent être à la source de LS, il vous faudra aller dans l’option suivante de Chrome :

Figure 11 - Layout Shifts Regions

 

Cela aura pour effet de faire flasher les régions concernées par des LS lors de la navigation sur la page :

Figure 12 -  LS provoqué par un cookie banner

 

Un autre outil permet de visualiser les layout shifts via la génération d’une image GIF : https://defaced.dev/tools/layout-shift-gif-generator/

Pour conclure, le CLS est une métrique très intéressante, car elle concerne l’expérience utilisateur, non seulement au chargement d’une page, mais pendant toute sa durée de vie. Une intégration HTML + CSS précise, qui tiendra compte des différentes dimensions des éléments, devrait vous permettre d’avoir un bon score CLS. En revanche, ce n'est pas un critère techniquement simple à implémenter, notamment sur un site web existant. Si votre site n'est pas conforme à ce sujet, il est probable qu'il nécessitera quelques développements complémentaires assez pointus...

 

Sources :

https://web.dev

https://css-tricks.com

https://noti.st/anniesullie/YLzlFd

 

 

Aymeric Bouillat, Consultant SEO senior chez Novalem (https://www.novalem.fr/)