Cumulative Layout Shift (CLS)
Cumulative Layout Shift (CLS) measures how much visible content moves around unexpectedly while a page is in use. Every time an element that is already on screen jumps to a new position without the visitor causing it, that shift is scored by how much of the viewport moved and how far. CLS is one of the three Core Web Vitals.
CLS is a unitless score, not a time. Lower is better; 0 means nothing shifted.
Why it matters
Layout shifts are more than an annoyance. A visitor starts reading and the text jumps away. They go to tap a link and an image loads above it, so they tap an ad or the wrong button instead. On a checkout page that can mean a wrong purchase. Google treats CLS as part of page experience, measured on real Chrome users.
What we check
We read the CLS value from the Lighthouse mobile run in PageSpeed Insights:
| Result | CLS |
|---|---|
| Good | 0.1 or less |
| Needs attention | over 0.1, up to 0.25 |
| Poor | over 0.25 |
The lab measurement covers the page load only, with no scrolling or clicking. Shifts that happen later, for example when a visitor scrolls and lazy-loaded content pushes things down, appear only in real-user field data. If your lab CLS is good but field CLS is not, look at what happens after load.
Common causes
- Images and videos without dimensions. The browser does not know how tall they are until they download, so content below them jumps.
- Ads, embeds and iframes that load into a container with no reserved height.
- Content injected above existing content: cookie banners, promo bars, “app install” notices.
- Web fonts that render with different metrics than the fallback font, reflowing text when they load.
- Animations that change
top,left,widthorheightinstead of usingtransform.
Shifts that happen within half a second of a visitor’s tap or keypress are expected and are not counted. A menu that opens when clicked is fine.
How to fix
Set width and height on every image and video. Browsers use the two attributes to compute the
aspect ratio and reserve the space before the file arrives. CSS can still make the image responsive:
<img src="/photo.webp" width="800" height="450" alt="..." />
img {
max-width: 100%;
height: auto;
}
Reserve space for ads, embeds and other late content. Give the container a minimum height that matches the most likely size:
.ad-slot {
min-height: 250px;
}
.video-embed {
aspect-ratio: 16 / 9;
}
If an ad slot sometimes stays empty, keep the reserved space anyway. Collapsing it causes a shift too.
Do not insert content above what the visitor is already seeing. Show banners as overlays fixed to the top or bottom of the viewport, or reserve their space in the initial HTML.
Tame font swaps. Preload the main web font, and use the size-adjust, ascent-override and
descent-override descriptors on the fallback @font-face so the fallback takes up the same space
as the final font. font-display: optional avoids the swap entirely on slow connections.
<link rel="preload" href="/fonts/inter.woff2" as="font" type="font/woff2" crossorigin />
Animate with transform and opacity. These do not affect the layout of other elements, so they
never cause layout shifts.
Finding the culprit
The Lighthouse report lists the elements that shifted the most. In Chrome DevTools, the Performance panel highlights layout shifts on the timeline and shows which nodes moved. Fix the largest shifts first; small ones often disappear once the big ones are gone.