Points clés à retenir
- Le CLS sur Shopify mesure les décalages inattendus de la mise en page. Chaque décalage a un score calculé selon la fraction d’impact multipliée par la fraction de distance, et ton CLS correspond à la pire série de décalages sur la page, pas au total.
- Les seuils de Google sont de 0,1 ou moins pour un bon score, et supérieurs à 0,25 pour un score médiocre, mesurés au 75e centile des chargements de pages réels.
- Le CLS en labo semble souvent bon alors que CrUX le juge médiocre, car un test en labo ne capture que les décalages qui se produisent pendant son propre chargement de page et sur un viewport fixe.
- La plupart des problèmes de CLS sur Shopify se résument à une courte liste : images sans dimensions, polices web, barres d’annonces, en-têtes fixes (sticky headers) et widgets injectés par des applications au-dessus de la ligne de flottaison.
- CrUX est une moyenne mobile sur 28 jours, donc un correctif déployé mettra jusqu’à quatre semaines pour se refléter complètement dans les données de terrain de PageSpeed Insights.
Le CLS sur Shopify mesure la façon dont le contenu bouge après le début du rendu de la page ; Google considère qu’un score de 0,1 ou moins est bon. L’acheteur s’apprête à cliquer sur le bouton Ajouter au panier, un widget d’avis se charge juste au-dessus, et le clic atterrit sur autre chose.
Ce guide t’explique comment le score est calculé, comment trouver l’élément responsable du décalage au lieu de deviner, et quelles causes spécifiques à Shopify vérifier en premier. La partie diagnostic s’applique à n’importe quel site. Les correctifs se font au niveau du thème et de Liquid.
Pourquoi vous pouvez nous faire confiance
Nous évoluons dans l’univers Shopify depuis plus de quatre ans et avons travaillé avec des centaines de marques sur leurs boutiques Shopify. Jacques a plus de 15 ans d’expérience en développement. Nous créons Fudge, l’opérateur IA pour les boutiques Shopify, qui a une note de 4.9 sur le Shopify App Store et le statut Built for Shopify, nous travaillons donc sur la même couche de thème où commencent les layout shifts.
Que mesure le CLS et comment le score est-il calculé ?
Le CLS mesure la plus grande rafale de décalages de mise en page inattendus (layout shift) qui se produit tout au long du cycle de vie d’une page.1
Deux mots de cette définition ont de l’importance.
« Inattendus ». Un décalage qui se produit dans les 500 millisecondes suivant une action utilisateur discrète, comme un tap, un clic ou l’appui sur une touche, reçoit l’indicateur hadRecentInput et est exclu.1 Le scroll, le glisser-déposer et le pincement pour zoomer ne comptent pas comme des entrées récentes, donc un décalage pendant le scroll impacte toujours le score.
« Plus grande rafale ». Le CLS n’est pas la somme de tous les décalages de la page. Les décalages sont regroupés en fenêtres de session (session windows) : une rafale de décalages espacés de moins d’une seconde chacun, avec une fenêtre totale maximale de cinq secondes.1 Votre CLS correspond à la fenêtre avec le score le plus élevé.
Fraction d’impact et fraction de distance
Chaque décalage individuel donne un score :
score de layout shift = fraction d'impact x fraction de distance
La fraction d’impact est la zone visible combinée de chaque élément instable entre l’image (frame) actuelle et la précédente, en tant que fraction de la surface du viewport.1
La fraction de distance est la plus grande distance parcourue par un élément instable dans cette frame, divisée par la plus grande dimension du viewport.1
La conséquence pratique : un petit élément qui se déplace beaucoup et un grand élément qui se déplace peu peuvent avoir le même score. Un hero en pleine largeur repoussé de 100px vers le bas sur mobile coûte cher, car la fraction d’impact est proche de 1.
Quel est un bon score CLS en 2026 ?
| Score | Évaluation |
|---|---|
| 0,1 ou moins | Bon |
| Plus de 0,1 à 0,25 | À améliorer |
| Plus de 0,25 | Médiocre |
Les seuils sont évalués au 75e centile des chargements de pages, segmentés séparément pour mobile et desktop.1 Ton visiteur médian peut avoir une expérience fluide alors que tu échoues quand même, car c’est le pire quart des chargements qui définit la note.
Google précise que les Core Web Vitals sont alignés sur ce que ses principaux systèmes de classement récompensent, et fixe 0,1 comme objectif de CLS.2 C’est un critère parmi d’autres, pas un interrupteur. Pour avoir une vision plus globale de la situation actuelle des boutiques Shopify, consulte notre rapport sur l’état des performances Shopify.
Pourquoi le CLS en Lab semble bon alors que CrUX est mauvais ?
C’est la confusion la plus courante, et ce n’est un bug dans aucun des deux outils.
Les données Lab représentent un seul chargement synthétique : un appareil émulé, un viewport, un cache vide, pas de scroll, pas d’interaction. Lighthouse signale les décalages qu’il observe pendant cette trace, puis s’arrête.
Les données terrain (Field data) proviennent de CrUX, agrégées à partir d’utilisateurs réels de Chrome tout au long du cycle de vie de la page. Elles incluent le décalage qui se produit quand quelqu’un fait défiler la page jusqu’aux avis, change une variante, ou attend sur une connexion lente qu’un widget d’application se charge.
Quatre différences expliquent ce décalage :
- Le timing. Sur une connexion rapide en laboratoire, un script tardif arrive avant le first paint et ne décale rien. Sur une vraie 4G, il arrive après.
- Les interactions. Les tests Lab ne scrollent jamais, donc une page de collection qui saute lors du chargement différé (lazy-load) semble parfaite.
- La taille du viewport. Une bannière qui passe sur deux lignes à 360px de large va décaler tout ce qui se trouve en dessous.
- La géographie. Les convertisseurs de devises et les bannières géolocalisées ne se déclenchent que pour certains visiteurs.
Si le Lab indique 0 et le terrain 0,3, fiez-vous aux données terrain et partez à la recherche des décalages liés aux interactions et au scroll.
Comment diagnostiquer le CLS sur une boutique Shopify
Commencez par analyser les données de terrain (field data), puis reproduisez le problème en local.
1. Lisez les données de terrain. Analysez l’URL en direct sur PageSpeed Insights et lisez la section CrUX en haut, et non le score Lighthouse en dessous. Vérifiez le mobile et le desktop, et testez séparément une page produit, une page collection et la page d’accueil. Le rapport Core Web Vitals de la Search Console regroupe les URL similaires, ce qui vous indique si le problème concerne un seul template ou tout le thème.
2. Enregistrez une trace. Dans le panneau Performance des Chrome DevTools, limitez le réseau à une connexion lente (throttling) et le CPU à 4x, puis enregistrez un rechargement. La piste Layout Shifts va se remplir de barres violettes. Cliquez sur un décalage individuel pour voir l’élément qui a bougé ainsi qu’une capture d’écran avant/après. L’insight “Layout shift culprits” met en évidence le pire cluster et propose une estimation de la cause.
3. Activez l’overlay. Dans DevTools, ouvrez Settings, puis More tools, puis Rendering, et cochez Layout Shift Regions. Les zones qui se décalent clignoteront en violet à chaque mouvement.3 C’est le moyen le plus rapide de repérer les petits décalages qui vous échapperaient sinon.
4. Traquez les décalages liés aux interactions. Les tests en labo ne les trouveront pas, alors générez-les manuellement avec la vue Live metrics du panneau Performance ouverte : scrollez toute la page, changez les variantes de produit, ouvrez le tiroir du panier, changez la devise, appliquez un filtre sur une page de collection. Regardez le chiffre CLS grimper et notez ce que vous faisiez à ce moment-là.
5. Instrumentez sur le terrain. Pour les décalages que vous n’arrivez pas à reproduire, loggez les vrais. L’API Layout Instability vous donne les nœuds responsables dans entry.sources :
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (!entry.hadRecentInput) {
console.log(
entry.value,
entry.sources.map((s) => s.node),
)
}
}
}).observe({type: 'layout-shift', buffered: true})
Chaque source contient previousRect et currentRect, vous pouvez donc voir exactement de combien de pixels un nœud s’est déplacé. Notez que l’élément qui a bougé est généralement la victime, pas le coupable. Le coupable est l’élément qui est apparu au-dessus.
Causes de CLS spécifiques à Shopify et leurs correctifs
| Cause | Correctif |
|---|---|
| Images ou vidéos sans dimensions | Attributs width et height, ou aspect-ratio sur le wrapper |
| Swap de Web font | font-display, preload du fichier de police, fallback avec métriques ajustées |
| Barre d’annonce ou livraison gratuite | Rendu en Liquid côté serveur, ou réserver une min-height |
| Bannière de cookies | Overlay en fixed en dehors du flux du document |
| Widgets d’apps (avis, devises, upsell) | App blocks avec un conteneur qui réserve une min-height |
| Contenu lazy-loadé above the fold | loading="eager" et fetchpriority="high" sur le hero |
| Header sticky | position: sticky, ou un spacer correspondant à la hauteur du header |
| Changement de variante | aspect-ratio fixe sur le wrapper du média produit |
| Scroll infini | Placeholders de type skeleton, ou un bouton Voir plus (Load more) |
| CSS de section arrivant tardivement | Charger le CSS above the fold de manière synchrone |
Images et vidéos sans dimensions
Définissez width et height pour que le navigateur réserve l’espace de la boîte avant même l’arrivée du fichier, puis laissez le CSS gérer le responsive :
<img src="hero.jpg" width="1600" height="900" alt="Collection Automne" />
img {
width: 100%;
height: auto;
}
En Liquid, le filtre image_tag génère les attributs width et height pour vous, calculés à partir de l’image source :
{{ product.featured_image | image_tag: widths: '400, 800, 1200', sizes: '(min-width: 750px) 50vw, 100vw' }}
Pour les vidéos, les intégrations (embeds), et tout ce qui n’a pas de taille intrinsèque, réservez l’espace directement sur le wrapper :
.video-wrapper {
aspect-ratio: 16 / 9;
}
Polices web et décalage lié au swap
Une police personnalisée se charge, remplace le fallback (police de secours), et chaque ligne de texte est recalculée. Si les deux polices ont des métriques différentes, le bloc change de hauteur et repousse le contenu vers le bas.
Trois correctifs, par ordre de difficulté :
Définissez font-display. Le filtre font_face de Shopify accepte directement ce paramètre :
{{ settings.type_body_font | font_face: font_display: 'swap' }}
swap affiche immédiatement la police de secours puis fait l’échange, donc le texte est toujours visible mais le décalage se produit quand même. optional évite complètement le décalage en refusant de faire le swap si la police met du temps à charger, au prix de certains visiteurs qui ne verront jamais la police de votre marque.
Préchargez le fichier (preload) pour que l’échange ait lieu avant le premier affichage (first paint) plutôt qu’après :
<link rel="preload" href="{{ settings.type_body_font | font_url }}" as="font" type="font/woff2" crossorigin>
Ajustez les métriques du fallback. Cela supprime le décalage sans renoncer à la police. Déclarez un fallback local avec des overrides ajustés sur votre web font, puis ajoutez-le dans la pile CSS :
@font-face {
font-family: 'Body Fallback';
src: local('Arial');
size-adjust: 103%;
ascent-override: 92%;
descent-override: 24%;
line-gap-override: 0%;
}
body {
font-family: 'Your Font', 'Body Fallback', sans-serif;
}
Les pourcentages sont spécifiques à chaque paire de polices. Mesurez-les plutôt que de copier ceux-ci.
Barres d’annonce, bannières de cookies et barres de livraison
Tout ce qui est injecté au-dessus de la ligne de flottaison repousse la page entière vers le bas, ce qui signifie une fraction d’impact proche de 1.
Générez-le en Liquid. Une barre qui arrive directement dans le HTML rendu par le serveur ne décale jamais rien, car elle était là dès la première frame. C’est le bon correctif dans presque tous les cas.
S’il faut que ce soit en JavaScript, réservez la hauteur avant le rendu :
.announcement-bar {
min-height: 40px;
}
Définissez la même valeur sur le placeholder pour chaque breakpoint où le texte passe sur une deuxième ligne. Une réservation de 40px pour une barre qui fait 72px sur un écran de 360px créera toujours un décalage.
Les bannières de cookies doivent être hors du flux. Utilisez position: fixed pour que la bannière se superpose au contenu au lieu de le déplacer.
Contenus injectés par des applications
Les widgets d’avis, convertisseurs de devises, blocs d’upsell, guides des tailles et bulles de chat se chargent tous tardivement et s’étendent dans la mise en page.
Privilégiez les app blocks (blocs d’application) ajoutés via l’éditeur de thème. Ils sont rendus à l’intérieur de la section, dans le flux du document, lors du rendu côté serveur. Les anciens widgets injectés par script arrivent après le paint et décalent tout ce qui se trouve en dessous.
Si l’application injecte toujours ses éléments tardivement, réservez l’espace du conteneur :
.shopify-app-block {
min-height: 24px;
}
.product-reviews-placeholder {
min-height: 180px;
}
Les bulles de chat doivent être en position: fixed, jamais dans le flux. Pour un guide étape par étape sur la façon d’isoler l’application responsable, consultez notre guide sur la résolution des problèmes de mise en page après l’installation d’apps Shopify.
Contenu above the fold chargé en lazy-load
Ajouter loading="lazy" sur une image hero (bannière) est une erreur qui provoque un décalage auto-infligé. Le navigateur retarde la récupération, l’espace reste vide pendant la fenêtre critique, et le contenu se met en place en retard.
Assurez-vous que le premier viewport bénéficie d’un chargement eager et d’une priorité élevée :
<img src="hero.jpg" width="1600" height="900" loading="eager" fetchpriority="high" alt="Hero" />
Tous les détails se trouvent dans notre guide pour corriger le chargement eager de la bannière hero Shopify.
Le même principe s’applique aux sections révélées par JavaScript. Les animations de fade-in qui animent height, top ou margin sont comptabilisées comme des layout shifts à chaque image. Animez plutôt transform et opacity, que le compositeur (compositor) gère sans reflow.
Sticky headers
Un header qui passe en position: fixed au défilement quitte le flux du document, et la page en dessous remonte d’une valeur égale à la hauteur du header.
Utilisez plutôt position: sticky, ce qui garde l’espace de l’élément réservé. Si le design exige d’être en fixed, insérez un élément espaceur de la même hauteur au moment où la classe bascule, et gardez les deux synchronisés avec une propriété CSS personnalisée.
Changement de variante sur la page produit
Il y a ici deux sources de décalage.
Des dimensions d’image différentes. Remplacer une image carrée par une variante en format portrait modifie la hauteur du bloc média. Verrouillez le wrapper :
.product-media {
aspect-ratio: 1 / 1;
}
.product-media img {
width: 100%;
height: 100%;
object-fit: contain;
}
Remplacements via la Section Rendering API. Re-rendre le formulaire produit lors d’un changement de variante remplace le balisage par un balisage de hauteur différente, généralement parce qu’un badge promo, une alerte de stock ou un sélecteur d’abonnement s’affiche pour une variante et pas pour une autre. Réservez une min-height sur la zone qui va être remplacée.
Ces décalages surviennent dans les 500ms après un clic, ils sont donc souvent exclus du calcul du CLS. Mais ils nuisent toujours à l’ergonomie, et tout reflow en cascade qui arriverait plus tard n’est pas exclu du calcul.
Scroll infini sur les pages de collection
L’ajout de produits à la suite repousse le footer et tout ce qui est actuellement visible. Réservez cet espace avec des placeholders de type skeleton dimensionnés sur les vraies lignes de la grille, ou utilisez un bouton “Voir plus” (Load more) pour que le décalage soit initié par l’utilisateur.
Pour les longues grilles, contenir la taille (size containment) aide le navigateur à bien anticiper les lignes hors écran :
.product-grid__item {
content-visibility: auto;
contain-intrinsic-size: auto 420px;
}
CSS qui arrive en retard
Les feuilles de style des sections chargées de manière asynchrone redessinent un contenu qui a déjà été affiché. Chargez le CSS des sections above the fold normalement et différez uniquement ce qui se trouve en dessous. Notre guide sur les scripts bloquant le rendu sur Shopify vous indique où se situe la limite.
Comment Fudge intervient
La plupart des correctifs ci-dessus sont de petites modifications spécifiques du Liquid, du CSS et du JavaScript du thème. Fudge, l’opérateur IA pour les boutiques Shopify, écrit ces modifications sous forme de code de thème natif plutôt que d’afficher une couche supplémentaire par-dessus ta boutique.
Demande de “Réserver la hauteur de la barre d’annonces à chaque breakpoint et verrouiller le ratio d’aspect sur le wrapper du média produit”, et la modification atterrit dans les fichiers de ton thème sous forme de brouillon que tu peux prévisualiser avant de le publier. Aucun script supplémentaire, aucun widget, ce qui compte quand la métrique que tu cherches à améliorer est causée par des scripts et des widgets supplémentaires. Il en va de même pour tout ce qui est construit avec l’éditeur de boutique Shopify : supprime Fudge et le code reste.
Fudge peut aussi s’occuper de la recherche. Demande un audit de vitesse et il listera ce qui ralentit tes pages, avec les correctifs préparés dans ton thème. Son travail sur la conversion aborde les mêmes problèmes du point de vue des ventes, comme les pages lentes et les mises en page qui cassent sur les petits écrans, et compare le taux de conversion sur chaque page avant et après la mise en ligne d’un correctif.
Comment vérifier le correctif et quand le CrUX se met à jour
La vérification se fait en trois étapes, et la dernière est lente.
Immédiatement : réenregistrez. Tracez à nouveau la page dans l’onglet Performance avec la même limitation réseau. La ligne Layout Shifts devrait être vide ou presque. Répétez l’opération avec les Layout Shift Regions activées, en faisant défiler toute la page et en changeant les variantes.
Sous 24h : vérifiez en Lab. Testez l’URL en direct sur PageSpeed Insights. Le CLS Lab confirme que les décalages liés au temps de chargement ont disparu, mais ne dit rien sur les décalages d’interaction, donc ne vous arrêtez pas là.
Sur 28 jours : observez le terrain. CrUX est une moyenne mobile sur 28 jours, mise à jour quotidiennement vers 04:00 UTC.4 Le lendemain du déploiement de votre correctif, 27 des 28 jours contiennent toujours la page avec le problème. L’amélioration apparaît progressivement et n’atteint sa vraie valeur qu’environ quatre semaines après que le correctif est en ligne pour tout le trafic.
Deux points trompent souvent les gens ici. Le correctif doit être publié sur le thème en ligne (live), car CrUX n’observe que les vrais visiteurs. Et une URL a besoin d’assez de trafic pour être signalée, de sorte que les pages peu fréquentées peuvent ne montrer que des données au niveau de l’origine du site.
Une fois le CLS réglé, la même boucle s’applique au reste des Web Vitals. Notre guide expliquant comment accélérer un thème Shopify couvre l’aspect du temps de chargement.
FAQ
Quel est un bon score CLS pour une boutique Shopify ?
0,1 ou moins est bon, au-dessus de 0,1 et jusqu'à 0,25 est à améliorer, et au-dessus de 0,25 est médiocre. Google évalue cela au 75e centile des chargements de pages réels, segmenté séparément pour mobile et desktop. Cela signifie que si plus d'un quart des chargements de page dépassent 0,1, la page échoue même si la plupart des visiteurs ne voient aucun décalage. Le mobile échoue généralement en premier, alors vérifie-le en priorité.
Pourquoi PageSpeed Insights montre-t-il un bon CLS en laboratoire mais médiocre dans les données de terrain ?
Un test en labo est un chargement synthétique sur un appareil émulé, sans défilement et sans interaction, il ne voit donc que les décalages qui se produisent pendant cette trace. Les données de terrain de CrUX proviennent d'utilisateurs réels de Chrome tout au long du cycle de vie de la page, y compris les décalages déclenchés par le scroll, le changement de variante et les scripts d'applications qui arrivent en retard sur des connexions lentes. Quand les deux ne sont pas d'accord, fie-toi aux données de terrain et cherche les décalages liés aux interactions et au scroll.
Les applications Shopify causent-elles du CLS ?
Fréquemment. Les widgets d'avis, les convertisseurs de devises, les blocs d'upsell et les bulles de chat injectent du contenu après le rendu de la page, poussant vers le bas ce qui se trouve en dessous. Les app blocks ajoutés via l'éditeur de thème sont plus sûrs car ils s'affichent dans le flux du document au moment du rendu côté serveur. Pour les widgets injectés par script, réserve l'espace avec un min-height sur le conteneur.
Comment trouver quel élément cause un layout shift sur ma boutique Shopify ?
Enregistre une trace dans le panneau Performance des Chrome DevTools avec le throttling activé, puis clique sur chaque décalage dans la piste Layout Shifts pour voir l'élément ainsi qu'une capture d'écran avant et après. En activant Layout Shift Regions dans l'onglet Rendering, les zones qui se décalent clignotent en violet en temps réel. N'oublie pas que l'élément qui a bougé est généralement la victime, et le coupable est ce qui est apparu au-dessus de lui.
Combien de temps faut-il pour qu'un correctif CLS apparaisse dans la Google Search Console ?
CrUX est une moyenne mobile sur 28 jours mise à jour quotidiennement, donc l'amélioration apparaît progressivement plutôt que du jour au lendemain. Compte environ quatre semaines après la mise en ligne du correctif sur le thème publié pour que le score de terrain reflète sa vraie valeur. Les outils de labo confirment le correctif immédiatement, mais ils ne couvrent que les décalages au chargement.
La barre d'annonces cause-t-elle du CLS sur Shopify ?
C'est le cas lorsqu'elle est injectée par JavaScript plutôt qu'affichée en Liquid, car elle apparaît au-dessus de tout le reste et pousse toute la page vers le bas. Afficher la barre côté serveur dans le thème supprime complètement le décalage. Si elle doit être dynamique, définis un min-height sur son conteneur qui correspond à la hauteur d'affichage à chaque breakpoint, y compris ceux où le texte s'enroule sur deux lignes.
Le CLS affecte-t-il le classement SEO sur Shopify ?
Google indique que les Core Web Vitals sont alignés sur ce que ses systèmes de classement récompensent, et fixe un CLS inférieur à 0,1 comme cible. C'est un signal parmi d'autres, pas un signal décisif. L'argument commercial le plus fort est généralement l'utilisabilité : une page qui bouge sous le pouce de l'acheteur entraîne de mauvais clics sur le bouton Ajouter au panier.
Footnotes
-
web.dev, “Cumulative Layout Shift (CLS)” - définition, la formule fraction d’impact multipliée par fraction de distance, l’écart d’une seconde et la fenêtre de session maximale de cinq secondes, l’exclusion
hadRecentInputde 500ms, et les seuils 0,1 / 0,25 au 75e centile. https://web.dev/articles/cls ↩ ↩2 ↩3 ↩4 ↩5 ↩6 -
Google Search Central, “Understanding Core Web Vitals and Google search results” - indique que l’expérience sur la page correspond à ce que les principaux systèmes de classement récompensent, et donne 0,1 comme objectif de CLS. https://developers.google.com/search/docs/appearance/core-web-vitals ↩
-
Chrome for Developers, “Discover issues with rendering performance” - l’option Layout Shift Regions de l’onglet Rendering surligne brièvement les zones qui se décalent en violet. https://developer.chrome.com/docs/devtools/rendering/performance ↩
-
Chrome for Developers, “CrUX API” - le Chrome UX Report est une moyenne mobile de 28 jours de métriques agrégées, mise à jour quotidiennement vers 04h00 UTC. https://developer.chrome.com/docs/crux/api ↩