What is CLS (Cumulative Layout Shift)?
CLS measures how much your page shifts unexpectedly during load. Learn what causes layout shifts, how they're scored, and how to eliminate them for a better user experience.
Cumulative Layout Shift (CLS) measures the visual stability of a page. It quantifies how much visible content unexpectedly shifts during the loading process. A high CLS score means your page is jumping around as elements load — frustrating users and causing accidental clicks.
CLS is one of Google’s three Core Web Vitals and a confirmed ranking factor. But beyond SEO, layout instability directly damages user trust and conversion rates.
How CLS Is Calculated
Since 2021, CLS reports the maximum session window of layout shifts — the largest burst of shifts within a 5-second window, with at least a 1-second gap between bursts. It is not the sum of all shifts over the page’s lifetime. Each individual shift score is still the product of two factors:
Impact fraction — the fraction of the viewport affected by the shift. Distance fraction — how far the largest shifted element moved, as a fraction of the viewport.
Layout shift score = impact fraction × distance fraction
Only unexpected shifts count. If a user clicks a button that expands a section, that’s an expected shift and doesn’t count against CLS. The CLS value is the total of shift scores within the worst session window, not the sum across the entire page lifetime.
CLS Thresholds
| Score | Rating |
|---|---|
| 0 – 0.1 | Good |
| 0.1 – 0.25 | Needs improvement |
| Over 0.25 | Poor |
As with all Core Web Vitals, Google measures at the 75th percentile of real user page loads.
What Causes Layout Shifts?
Images without dimensions
The most common cause. When you load an <img> without width and height attributes, the browser doesn’t know how much space to reserve until the image downloads. Everything below shifts down.
<!-- Bad: no dimensions -->
<img src="photo.jpg" alt="..." />
<!-- Good: explicit dimensions -->
<img src="photo.jpg" width="800" height="600" alt="..." />
Ads and embeds that load late Ads that load after the page has rendered push content down. Iframes for social embeds, YouTube videos, and widgets cause the same problem.
Web fonts causing FOUT/FOIT
Fonts that load after the page text cause invisible or fallback text to be replaced, often reflow the layout. The font-display: swap strategy can cause this.
Dynamically injected content Banners, cookie notices, and popups injected above existing content after load cause large shifts.
Animations that affect layout
CSS animations that change top, left, margin, padding, or other layout-affecting properties cause layout shifts. Use transform and opacity instead — they’re composited and don’t trigger layout.
How to Fix CLS
Always set width and height on images
Use the aspect-ratio CSS property as a modern alternative:
img {
aspect-ratio: 16 / 9;
width: 100%;
}
Reserve space for ads and embeds Wrap ad slots in a container with a minimum height set to the expected ad size before it loads.
Use font-display: optional or preload fonts
<link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin />
font-display: optional prevents visible fallback text and eliminates reflow — at the cost of potentially not showing the custom font on first load.
Avoid inserting content above existing content
If you must show a banner or notice, use a fixed position (position: fixed) so it doesn’t affect layout flow.
Animate with transform only
/* Bad — causes layout shift */
.slide-in { animation: slide-in 0.3s; }
@keyframes slide-in { from { margin-top: -20px; } }
/* Good — composited, no layout shift */
.slide-in { animation: slide-in 0.3s; }
@keyframes slide-in { from { transform: translateY(-20px); } }
Finding Your CLS Issues
Run a free test on debugutils.dev. The filmstrip view shows you exactly when layout shifts occur during load, making it easy to identify which element is causing the problem. This is far more useful than just getting a CLS number. For a step-by-step fix guide, see How to Fix CLS.