
Cumulative Layout Shift (CLS) scores how much visible content unexpectedly moves around while a user is on the page. It is the visual-stability metric of Core Web Vitals, and the only one of the three measured in unitless score rather than time: 0.1 or less is good, 0.1–0.25 needs improvement, above 0.25 is poor, at the 75th percentile of real visits.
Everyone has felt the failure mode: you go to tap "Confirm" and an ad loads above it, the page lurches, and you tap "Delete" instead. Layout shift is the one performance problem users actively curse at. It also has a special property for auditors — it's usually cheap to fix, because the causes are mostly missing attributes, not architecture.
How the score is actually calculated
Each unexpected shift gets a score: impact fraction × distance fraction. Impact fraction is how much of the viewport the moving elements occupied (before plus after); distance fraction is how far they moved as a share of the viewport's largest dimension. An element filling half the screen that jumps a quarter of the screen down scores 0.75 × 0.25 ≈ 0.19 — already past the "good" line from one shift.
Individual shifts are then grouped into session windows: shifts less than a second apart, capped at five seconds per window. Your CLS is the worst window's total, not the sum of everything that ever moved. Two consequences worth knowing:
- A page that shifts once badly can score worse than one that micro-shifts occasionally all day.
- Shifts within 500 ms of a user interaction are excused — expanding an accordion the user clicked doesn't count. Movement the user caused is fine; movement that happens to them is not.
What shifts pages — and what pins them down
| Shift source | What the user sees | Prevention |
|---|---|---|
| Images without dimensions | Text renders, then jumps down as each image arrives | width and height attributes on every <img>; the browser reserves the box before the file loads |
| Ads, embeds, iframes | Content lurches when the ad server responds (or worse: resizes again on refresh) | Reserve a fixed slot with min-height sized to the largest expected creative; never collapse empty slots |
| Webfonts | Whole page reflows when the custom font swaps in with different metrics | font-display: swap plus size-adjust/fallback metric tuning; preload the font file |
| Cookie banners & notice bars | Everything shoves down half a second after render | Overlay it (position: fixed) or reserve the space in the initial layout |
| Late-injected content | "Related products" block appears mid-scroll and yanks the page | Skeleton placeholders at final size; insert below the current viewport, never above |
| Animating layout properties | Elements pushed around by top/height animations | Animate transform instead — transforms don't count as layout shifts |
The fixes in code
<!-- 1. Dimensioned image: browser computes aspect ratio, reserves space -->
<img src="/img/chart.webp" width="800" height="450" alt="...">
<!-- 2. Responsive element without intrinsic size: reserve via CSS -->
<style>
.ad-slot { min-height: 280px; } /* tallest expected creative */
.video-embed { aspect-ratio: 16 / 9; } /* holds the box before iframe loads */
</style>
<!-- 3. Webfont that swaps without reflow -->
<style>
@font-face{
font-family: 'Brand';
src: url('/fonts/brand.woff2') format('woff2');
font-display: swap;
}
@font-face{ font-display:swap;
font-family: 'Brand-fallback';
src: local('Arial');
size-adjust: 104%; /* match fallback metrics to the webfont */
}
</style>That first pattern alone — width/height on images — resolves the majority of CLS failures I see. Modern browsers use the attributes to compute an aspect ratio even when CSS makes the image fluid, so there is no responsive-design excuse for omitting them. Details in add dimensions to images.
How to check CLS on your own site
- Search Console → Core Web Vitals: look for "CLS issue: more than 0.1" URL groups to find affected templates.
- PageSpeed Insights: field CLS first, then the lab's "Avoid large layout shifts" audit — it lists the exact elements and each one's score contribution.
- Chrome DevTools Performance panel: record a load; the Layout Shifts track highlights each shift, and clicking one shows what moved from where to where. Screenshots on the timeline make the culprit obvious.
- DevTools Rendering tab → "Layout Shift Regions": browse your page normally and every shifting element flashes blue. Fastest gut-check there is.
- web-vitals library:
onCLS(console.log)with the attribution build names the largest shifting element in real field sessions — critical, because lab loads don't scroll, and plenty of shifts only happen mid-scroll.
Common mistakes in CLS audits
- Trusting a clean lab score. Lighthouse loads the page and stops. Shifts triggered by scrolling, lazy content, or slow ad calls never fire in the lab, so field CLS can be poor while lab shows 0.00. This metric more than any other needs field data (field vs lab explained).
- Sizing the ad slot for the average creative. The slot must fit the largest one; a 90 px reservation holding a 250 px banner still shifts 160 px.
- Fixing images but not fonts. Font-swap reflow moves every line of text on the page — small distance, huge impact fraction, so it adds up fast on text-heavy pages.
- Forgetting the late hero. A slow, undimensioned hero image is a double failure: it drags LCP late and shoves everything below it when it finally lands. One reserved box fixes both.
- Injecting banners above existing content. Promo bars, "app available" nags, review widgets — if it appears after first paint, it must overlay or be pre-reserved. Never push.
Frequently asked questions
Is CLS only measured during page load?
No — that's the biggest misconception about it. CLS accumulates for the whole lifetime of the page, including shifts that happen five minutes in while the user scrolls. That's also why lab tools systematically underreport it.
My layout is responsive — do width/height attributes still work?
Yes. The attributes feed the browser an intrinsic aspect ratio; your CSS (max-width: 100%; height: auto) still controls the displayed size. You get fluid images and reserved space.
Do user-triggered changes count against CLS?
Shifts within 500 ms of a discrete interaction (tap, click, keypress) are excluded. But if the user clicks and your content arrives 800 ms later and shoves the page, that counts. Slow responses turn excused shifts into penalized ones.
What's a realistic target?
Genuinely 0.0x. Unlike LCP, where physics sets a floor, layout stability is fully within your control — a page with reserved boxes simply does not shift. The CLS fixing guide and the complete CLS guide cover the full remediation path.
Claude Vincent is a technical SEO consultant focused on crawlability, rendering, and AI-search visibility. He writes the field guides and case studies at SEO ProCheck, with a bias toward the durable, unglamorous work that decides whether search engines and AI answer engines can actually read and cite a site.
About SEO ProCheck
Technical SEO consulting and GEO strategy with 20 years of enterprise experience. Case studies, resources, and tools for search and AI visibility.
Work With Me
Technical SEO audits, GEO strategy, site migrations, and international SEO. Hourly consulting for teams who need hands-on support, not just reports.







