Skip to main content

How to Fix Cumulative Layout Shift (CLS)

4 min readBy SEO Snapshot

What CLS measures and why it feels so annoying

Cumulative Layout Shift scores how much the page jumps around while it loads. You know the feeling: you go to tap a button, an ad or image loads above it, and the whole layout lurches down so you tap the wrong thing. CLS puts a number on that. Google grades it at 0.1 or below for a good score at the 75th percentile; 0.1–0.25 needs improvement, and above 0.25 is poor.

The score is unitless — it's the fraction of the viewport that moved multiplied by the distance it moved, summed over the load. Unlike LCP, which is about speed, CLS is about stability, and the fixes are almost entirely about reserving space before content arrives.

The usual suspects, in order

1. Images and videos without dimensions. This is the number-one cause. When an <img> has no width and height, the browser reserves zero space, renders the text, then shoves everything down when the image arrives. The fix is to always set the intrinsic dimensions and let CSS scale it responsively:

<img src="/chart.webp" width="1200" height="630" alt="Traffic chart"
     style="max-width:100%; height:auto;">

The browser uses those numbers to compute an aspect ratio and reserve the box before the file loads. The analyzer flags every image missing dimensions — it's the single most common layout-shift check it reports.

2. Web fonts swapping in. When a fallback font renders first and your web font swaps in with different metrics, text reflows. Reduce it by preloading the font and using the size-adjust and font-display: optional descriptors, or matching the fallback's metrics:

@font-face {
  font-family: 'Inter';
  src: url('/inter.woff2') format('woff2');
  font-display: swap;
  size-adjust: 100%;
}

3. Injected content: ads, embeds, banners. Anything inserted after render — a cookie banner, an ad slot, a newsletter box, an embedded tweet — pushes content down unless you reserve space for it. Give ad and embed containers a fixed min-height matching their typical size:

.ad-slot { min-height: 280px; }
.embed-container { aspect-ratio: 16 / 9; }

4. Content inserted above existing content. A "we use cookies" bar or a promo banner that loads at the top and pushes the article down is a classic offender. Either reserve its height in advance, or position it as an overlay (position: fixed) so it doesn't participate in layout flow.

Measuring it honestly

CLS is measured across the entire page lifecycle, not just the initial load, so shifts triggered by scrolling or late-loading widgets count too — but only shifts that happen without user interaction. A layout change within 500ms of a click or tap is excused, because that's usually intentional (opening an accordion, loading more results). This is why a page can feel janky to you but score fine, or vice versa.

Use the DevTools Performance panel's "Experience" row to see each shift flagged with the exact element that moved. In the field, the Chrome UX Report and Search Console's Core Web Vitals report give you the real 75th-percentile number. As with the other Core Web Vitals, the field data is a rolling 28-day average, so give a fix a few weeks to show up.

A realistic before-and-after

A blog with a 0.32 CLS — unsized images, a web font swap, and a cookie banner injected at the top — typically drops to under 0.05 with three changes: adding width/height to every image (the image SEO basics cover this alongside alt text and formats), reserving the cookie banner's height, and preloading the font. CLS is one of the more satisfying vitals to fix because the wins are visible: the page simply stops jumping.

FAQ

Q: What causes most layout shift? A: Images and iframes without explicit width and height attributes. The browser reserves no space for them, renders surrounding content, then pushes it aside when the media loads. Setting intrinsic dimensions (and letting CSS scale responsively) fixes the majority of CLS problems.

Q: Do layout shifts from clicking count against CLS? A: No. Shifts that happen within 500 milliseconds of a user interaction are excluded, because they're usually intentional — like expanding a menu or loading more content. Only unexpected shifts count.

Q: What's a good CLS score? A: 0.1 or lower at the 75th percentile of real page loads. Between 0.1 and 0.25 needs improvement, and above 0.25 is poor.

Q: How do I reserve space for ads and embeds? A: Give their containers a fixed min-height or an aspect-ratio in CSS that matches the content's typical size, so the browser holds the space before the ad or embed loads instead of shifting content when it arrives.

Check your site's SEO score for free

Analyze your site