Understanding Cumulative Layout Shift (CLS) and How to Fix It
Cumulative Layout Shift measures visual stability — how much your page's content unexpectedly jumps around as it loads. It's the Core Web Vital most likely to genuinely annoy your visitors, since it's the one they can literally see happening: you go to tap a button and the page shifts right as your finger lands, hitting an ad instead. Here's how to diagnose and fix it.
What CLS Actually Measures
CLS calculates a score based on how much visible content moves, and how far it moves, during the page's loading lifecycle. A score under 0.1 is considered good, 0.1-0.25 needs improvement, and above 0.25 is poor. Unlike LCP or TBT which measure speed, CLS measures stability — a page can load fast and still have terrible CLS if content keeps jumping around during that fast load.
The Most Common Cause: Images Without Dimensions
By far the most frequent CLS culprit is images (or videos, or embeds) that don't have explicit width and height attributes. When the browser doesn't know an image's dimensions ahead of time, it renders the surrounding content first, then suddenly makes room once the image finishes loading — pushing everything below it downward.
The fix is simple: always specify width and height attributes on <img> tags (or use aspect-ratio in CSS), so the browser reserves the correct space before the image loads, regardless of when the actual image data arrives.
Web Fonts Causing Text Reflow
When a custom web font loads after initial text render (using a fallback font first), the change in font metrics — different character widths, line heights — can cause text to reflow and shift surrounding content. Using font-display: optional or carefully matching fallback font metrics to your custom font reduces this. Preloading your font file also helps it arrive earlier, reducing the window where a shift can occur.
Dynamically Injected Content
Ads, embeds, banners, and cookie consent notices that get injected into the page after initial load are a major CLS offender, especially when they appear above existing content and push everything else down. Solutions:
- Reserve space for ad slots in advance using a fixed-size container, even before the ad loads.
- Position injected banners (cookie notices, promotional bars) as overlays rather than pushing content down, or reserve their space in the initial layout.
- Avoid inserting new content above the fold after the user has already started interacting with the page.
Animations That Trigger Layout
Not all animations are equal from a CLS perspective. Animating properties like width, height, top, or left triggers layout recalculation and can count against CLS. Prefer animating transform and opacity instead, which the browser can handle on the compositor thread without triggering a full layout reflow.
Late-Loading Third-Party Widgets
Chat widgets, social media embeds, and similar third-party scripts often inject their UI after the rest of the page has already rendered, causing a visible shift when they appear. Where possible, reserve space for these elements in your initial layout, or load them with a placeholder of the correct size already in place.
Measuring and Debugging CLS
Chrome DevTools' Performance panel includes a "Layout Shift" section that visually highlights exactly which elements caused shifts and by how much, which is far more useful than just seeing the aggregate score. Real-user monitoring data (via Chrome UX Report or your own analytics) also matters more than lab data here, since CLS can vary significantly based on actual device performance and network speed, which lab tests may not fully capture.
The Bottom Line
CLS is one of the more fixable Core Web Vitals because the causes are usually structural, not algorithmic — reserve space for images and dynamic content, be careful with font loading, and avoid layout-triggering animations. Most sites can get CLS into the "good" range without major redesign work, just by being deliberate about how and when content is allowed to appear.
