Cumulative Layout Shift (CLS)

Milica Mihajlija
Milica Mihajlija
Philip Walton
Philip Walton

Navigateurs pris en charge

  • Chrome : 77.
  • Edge : 79.
  • Firefox: non compatible.
  • Safari : non compatible.

Source

Les changements de mise en page inattendus peuvent perturber l'expérience utilisateur de différentes manières, par exemple en lui faisant perdre sa place pendant la lecture si le texte se déplace soudainement, ou en l'incitant à cliquer sur le mauvais lien ou bouton. Dans certains cas, cela peut causer des dommages graves.

Un changement soudain de mise en page oblige l'utilisateur à confirmer une commande importante qu'il avait l'intention d'annuler.

Le déplacement inattendu du contenu de la page se produit généralement lorsque les ressources sont chargées de manière asynchrone ou que des éléments DOM sont ajoutés de manière dynamique à la page avant le contenu existant. Ces décalages peuvent être dus à des images ou des vidéos dont les dimensions sont inconnues, à des polices dont l'affichage est supérieur ou inférieur à celui de la création de remplacement initiale, ou à des annonces ou widgets tiers qui se redimensionnent de manière dynamique.

Les différences entre le fonctionnement d'un site pendant le développement et celui de ses utilisateurs aggravent le problème. Exemple :

  • Les contenus personnalisés ou tiers se comportent souvent différemment en développement et en production.
  • Les images de test sont souvent déjà dans le cache du navigateur du développeur, mais elles prennent plus de temps à se charger pour l'utilisateur final.
  • Les appels d'API exécutés localement sont souvent si rapides que les retards imperceptibles en développement peuvent devenir importants en production.

La métrique CLS (Cumulative Layout Shift) vous aide à résoudre ce problème en mesurant la fréquence à laquelle il se produit pour des utilisateurs réels.

Qu'est-ce que le CLS ?

Le CLS mesure la plus grande rafale de scores de décalage de mise en page pour chaque décalage de mise en page inattendu sur toute la durée de vie d'une page.

Un décalage de mise en page se produit chaque fois qu'un élément visible change de position d'un frame à l'autre. (Vous trouverez plus d'informations sur le calcul des scores de décalage de mise en page individuels plus loin dans ce guide.)

Une fenêtre de session est une série de changements de mise en page qui se produisent rapidement, avec un intervalle de moins d'une seconde entre chaque changement et une durée totale de la fenêtre maximale de cinq secondes.

La plus grande rafale correspond à la fenêtre de session avec le score cumulé maximal de tous les décalages de mise en page dans cette fenêtre.

Exemple de fenêtres de session. Les barres bleues représentent les scores de chaque décalage de mise en page individuel.

Qu'est-ce qu'un bon score CLS ?

Pour offrir une expérience utilisateur de qualité, les sites doivent s'efforcer d'obtenir un score CLS de 0,1 ou moins. Pour vous assurer d'atteindre cet objectif pour la plupart de vos utilisateurs, nous vous recommandons de mesurer le 75e centile des chargements de pages, segmentés par appareil mobile et ordinateur.

Les bonnes valeurs CLS sont inférieures ou égales à 0,1, les valeurs faibles sont supérieures à 0,25, et tout élément entre les deux doit être amélioré.
Une valeur CLS de 0,1 ou moins est considérée comme bonne. Les valeurs médiocres sont supérieures à 0,25.

Pour en savoir plus sur les recherches et la méthodologie à l'origine de cette recommandation, consultez Définir les seuils des métriques Core Web Vitals.

Décalages de mise en page détaillés

Les décalages de mise en page sont définis par l'API Layout Instability, qui signale des entrées layout-shift chaque fois qu'un élément visible dans le viewport modifie sa position de départ (par exemple, sa position en haut et à gauche dans le mode d'écriture par défaut) entre deux frames. Ces éléments sont considérés comme des éléments instables.

Notez que les décalages de mise en page ne se produisent que lorsque la position de départ des éléments existants change. Si un nouvel élément est ajouté au DOM ou si la taille d'un élément existant change, cela ne compte pas comme un décalage de mise en page, à condition que ce changement ne modifie pas la position de départ d'autres éléments visibles.

Score de décalage de mise en page

Pour calculer le score de décalage de mise en page, le navigateur examine la taille de la fenêtre d'affichage et le mouvement des éléments instables dans la fenêtre d'affichage entre deux frames affichés. Le score de décalage de mise en page est un produit de deux mesures de ce mouvement: la fraction d'impact et la fraction de distance (toutes deux définies ci-dessous).

layout shift score = impact fraction * distance fraction

Fraction d'impact

La fraction d'impact mesure l'impact des éléments instables sur la zone de la fenêtre d'affichage entre deux images.

La fraction d'impact d'un frame donné correspond à la combinaison des zones visibles de tous les éléments instables de ce frame et du frame précédent, en tant que fraction de la surface totale de la fenêtre d'affichage.

Exemple de fraction d'impact avec un élément instable
Si un élément change de position, sa position précédente et sa position actuelle contribuent à sa fraction d'impact.

Dans l'image précédente, un élément occupe la moitié de la fenêtre d'affichage dans un seul frame. Ensuite, dans le frame suivant, l'élément est décalé vers le bas de 25 % de la hauteur de la fenêtre d'affichage. Le rectangle rouge en pointillé indique l'union de la zone visible de l'élément dans les deux cadres, qui, dans ce cas, représente 75% de la fenêtre d'affichage totale. Sa fraction d'impact est donc 0.75.

Fraction de distance

L'autre partie de l'équation du score de décalage de mise en page mesure la distance parcourue par les éléments instables par rapport à la fenêtre d'affichage. La fraction de distance correspond à la plus grande distance horizontale ou verticale qu'un élément instable a parcourue dans le frame, divisée par la plus grande dimension de la fenêtre d'affichage (largeur ou hauteur, selon la valeur la plus élevée).

Exemple de fraction de distance avec un élément instable
La fraction de distance mesure la distance parcourue par un élément dans la fenêtre d'affichage.

Dans l'exemple précédent, la plus grande dimension de la fenêtre d'affichage est la hauteur, et l'élément instable a été déplacé de 25% de la hauteur de la fenêtre d'affichage, ce qui donne une fraction de distance de 0,25.

Dans cet exemple, la fraction d'impact est 0.75 et la fraction de distance est 0.25. Le score de décalage de mise en page est donc 0.75 * 0.25 = 0.1875.

Exemples

L'exemple suivant montre comment l'ajout de contenu à un élément existant affecte le score de décalage de mise en page :

Exemple de décalage de mise en page avec plusieurs éléments stables et _instables_
L'ajout d'un bouton en bas de la boîte grise pousse celle-ci vers le bas et en partie hors de la fenêtre d'affichage.

Dans cet exemple, la zone grise change de taille, mais sa position de départ ne change pas. Il ne s'agit donc pas d'un élément instable.

Le bouton "Cliquez ici !" n'était pas auparavant dans le DOM. Sa position de départ ne change donc pas non plus.

La position de départ de la zone verte change, mais comme elle a été partiellement déplacée en dehors du viewport, la zone invisible n'est pas prise en compte lors du calcul de la fraction d'impact. L'union des zones visibles de la zone verte dans les deux cadres (illustrée par le rectangle rouge en pointillés) est identique à la zone de la zone verte dans le premier cadre (50 % de la fenêtre d'affichage). La fraction d'impact est 0.5.

La fraction de distance est illustrée par la flèche violette. La boîte verte a été déplacée d'environ 14% vers le bas de la fenêtre d'affichage. La fraction de distance est donc de 0.14.

Le score de décalage de mise en page est 0.5 x 0.14 = 0.07.

L'exemple suivant montre comment plusieurs éléments instables affectent le score de changement de mise en page d'une page:

Exemple de décalage de mise en page avec des éléments stables et _instables_, et rognage de la fenêtre d'affichage
À mesure que de nouveaux noms apparaissent dans cette liste triée, les noms existants sont déplacés pour préserver l'ordre alphabétique.

Dans le premier frame de l'image précédente, vous pouvez voir quatre résultats d'une requête d'API pour des animaux, triés par ordre alphabétique. Dans le deuxième frame, d'autres résultats sont ajoutés à la liste triée.

Le premier élément de la liste ("Chat") ne change pas de position de départ entre les images. Il est donc stable. De même, les nouveaux éléments ajoutés à la liste ne figuraient pas auparavant dans le DOM. Par conséquent, leurs positions de départ ne changent pas non plus. Cependant, les éléments intitulés "Chien", "Cheval" et "Zèbre" changent tous de position de départ, ce qui les rend instables.

Encore une fois, les rectangles rouges en pointillés représentent l'union des zones avant et après de ces trois éléments instables, qui dans ce cas représente environ 60% de la zone de la fenêtre d'affichage (fraction d'impact de 0.60).

Les flèches représentent les distances parcourues par les éléments instables par rapport à leur position de départ. L'élément "Zèbre", représenté par la flèche bleue, a été déplacé le plus, d'environ 30% de la hauteur de la fenêtre d'affichage. La fraction de distance dans cet exemple est donc 0.3.

Le score de décalage de mise en page est de 0.60 x 0.3 = 0.18.

Décalages de mise en page attendus et inattendus

Les décalages de mise en page ne sont pas tous négatifs. En fait, de nombreuses applications Web dynamiques modifient fréquemment la position de départ des éléments sur la page. Un décalage de mise en page n'est négatif que si l'utilisateur ne s'y attend pas.

Décalages de mise en page déclenchés par l'utilisateur

Les changements de mise en page qui se produisent en réponse aux interactions de l'utilisateur (par exemple, cliquer ou appuyer sur un lien, appuyer sur un bouton ou saisir du texte dans un champ de recherche) sont généralement acceptables, à condition que le changement se produise suffisamment près de l'interaction pour que la relation soit claire pour l'utilisateur.

Par exemple, si une interaction utilisateur déclenche une requête réseau dont l'exécution peut prendre un certain temps, il est préférable de créer immédiatement de l'espace et d'afficher un indicateur de chargement pour éviter un décalage de mise en page désagréable à la fin de la requête. Si l'utilisateur ne se rend pas compte que quelque chose est en cours de chargement ou qu'il ne sait pas quand la ressource sera prête, il peut essayer de cliquer sur autre chose pendant qu'il attend, ce qui pourrait entraîner la disparition de l'élément.

L'indicateur hadRecentInput sera défini pour les décalages de mise en page qui se produisent dans les 500 millisecondes après une entrée utilisateur. Ils pourront donc être exclus des calculs.

Animations et transitions

Les animations et les transitions, lorsqu'elles sont bien conçues, sont un excellent moyen de mettre à jour le contenu de la page sans surprendre l'utilisateur. Les contenus qui changent brusquement et de manière inattendue sur la page génèrent presque toujours une mauvaise expérience utilisateur. Toutefois, les contenus qui se déplacent progressivement et naturellement d'une position à l'autre peuvent souvent aider l'utilisateur à mieux comprendre ce qui se passe et à le guider entre les changements d'état.

Veillez à respecter les paramètres du navigateur prefers-reduced-motion, car certains visiteurs peuvent subir des effets néfastes ou des problèmes d'attention en raison de l'animation.

La propriété CSS transform vous permet d'animer des éléments sans déclencher de décalages de mise en page :

  • Au lieu de modifier les propriétés height et width, utilisez transform: scale().
  • Pour déplacer des éléments, évitez de modifier les propriétés top, right, bottom ou left et utilisez plutôt transform: translate().

Mesurer le CLS

La CLS peut être mesurée en laboratoire ou sur le terrain. Elle est disponible dans les outils suivants:

Outils sur le terrain

Outils de l'atelier

Mesurer les décalages de mise en page en JavaScript

Pour mesurer les décalages de mise en page en JavaScript, utilisez l'API Layout Instability.

L'exemple suivant montre comment créer un PerformanceObserver pour consigner les entrées layout-shift dans la console:

new PerformanceObserver((entryList) => {
  for (const entry of entryList.getEntries()) {
    console.log('Layout shift:', entry);
  }
}).observe({type: 'layout-shift', buffered: true});

Mesurer le CLS en JavaScript

Pour mesurer le CLS en JavaScript, vous devez regrouper ces entrées layout-shift inattendues en sessions et calculer la valeur maximale de la session. Vous pouvez consulter le code source de la bibliothèque JavaScript web vitals, qui contient une implémentation de référence sur le calcul du CLS.

Dans la plupart des cas, la valeur CLS actuelle au moment du déchargement de la page est la valeur CLS finale de cette page. Toutefois, il existe quelques exceptions importantes, comme indiqué dans la section suivante. La bibliothèque JavaScript web vitals en tient compte dans la mesure du possible, dans les limites des API Web.

Différences entre la métrique et l'API

  • Si une page est chargée en arrière-plan ou si elle est mise en arrière-plan avant que le navigateur ne peigne du contenu, aucune valeur CLS ne doit être renvoyée.
  • Si une page est restaurée à partir du cache "Retour/Avant", sa valeur CLS doit être réinitialisée à zéro, car les utilisateurs la perçoivent comme une visite de page distincte.
  • L'API ne signale pas les entrées layout-shift pour les décalages qui se produisent dans les iFrames, mais la métrique le fait, car ils font partie de l'expérience utilisateur de la page. Cela peut se traduire par une différence entre les formats CrUX et RUM. Vous devez en tenir compte pour mesurer correctement le CLS. Les sous-frames peuvent utiliser l'API pour signaler leurs entrées layout-shift au frame parent à des fins d'agrégation.

En plus de ces exceptions, la métrique CLS est plus complexe, car elle mesure l'ensemble de la durée de vie d'une page :

  • Les utilisateurs peuvent garder un onglet ouvert pendant très longtemps (des jours, des semaines ou des mois). En fait, il est possible qu'un utilisateur ne ferme jamais un onglet.
  • Sur les systèmes d'exploitation mobiles, les navigateurs n'exécutent généralement pas de rappels de déchargement de page pour les onglets en arrière-plan, ce qui rend difficile le rapport de la valeur "finale".

Pour gérer de tels cas, le CLS doit être signalé chaque fois qu'une page est en arrière-plan, et non pas à chaque fois qu'elle est déchargée (l'événement visibilitychange couvre ces deux scénarios). Les systèmes d'analyse qui reçoivent ces données devront ensuite calculer la valeur CLS finale sur le backend.

Plutôt que de mémoriser et de gérer vous-même tous ces cas, les développeurs peuvent utiliser la bibliothèque JavaScript web-vitals pour mesurer le CLS, qui tient compte de tout ce qui est mentionné ci-dessus, à l'exception du cas d'iFrame :

import {onCLS} from 'web-vitals';

// Measure and log CLS in all situations
// where it needs to be reported.
onCLS(console.log);

Améliorer le CLS

Pour en savoir plus sur l'identification des décalages de mise en page sur le terrain et sur l'utilisation des données de laboratoire pour les optimiser, consultez notre guide sur l'optimisation du CLS.

Ressources supplémentaires

Journal des modifications

Il arrive que des bugs soient détectés dans les API utilisées pour mesurer les métriques, et parfois dans les définitions des métriques elles-mêmes. Par conséquent, des modifications doivent parfois être apportées, et ces modifications peuvent apparaître comme des améliorations ou des régressions dans vos rapports et tableaux de bord internes.

Pour vous aider à gérer ce point, toutes les modifications apportées à l'implémentation ou à la définition de ces métriques seront indiquées dans ce journal des modifications.

Si vous avez des commentaires sur ces métriques, vous pouvez les envoyer dans le groupe Google web-vitals-feedback.