Skip to content
SEO Optimizer is live, Audit on page SEO and AI-search readiness. Try it free
Sign in

How to Fix Cumulative Layout Shift (CLS)

CLS measures how much visible content unexpectedly moves around while your page loads - a button that shifts right as you go to tap it, or text that jumps down the page mid-read. Google's threshold for "good" is a score of 0.1 or below, and it's one of the three official Core Web Vitals.

Why Your Page Is Shifting

Almost every CLS problem comes from one of three sources:

  • Images and iframes with no reserved dimensions. If the browser doesn't know an image's size before it loads, it renders the box at zero height, then snaps everything below it downward the instant the image arrives.
  • Content injected above existing content. Ads, promo bars, and cookie banners that get inserted into the DOM after the initial render push everything below them down.
  • Web fonts that reflow text on swap. A fallback font renders first, then the real font loads and swaps in at a different width/height, reflowing every line it touches.

How to Identify What's Shifting

Scanverra's performance checks score CLS directly from a real Lighthouse run against your live URL, using the same cumulative-layout-shift metric Google's field data is built on. When it's high, Scanverra flags it as a distinct issue - not just a number, but a named problem - because an unstable layout also breaks something else: an AI agent or automated tool trying to click a button that just moved will target the wrong element.

To find the specific offending element, Chrome DevTools' Performance panel records "Layout Shift" entries with the exact node that moved and by how much - open it, record a page load, and look for the red layout-shift markers in the Experience track.

How to Fix It

1. Reserve space with explicit dimensions

Every image, video, and iframe should declare its width and height (or use modern CSS aspect-ratio) so the browser can allocate the correct box before the resource arrives:

components/ProductImage.tsxExplicit width/height reserves the box up front
<img
  src="/product.webp"
  alt="Wireless keyboard, top view"
  width={640}
  height={480}
  loading="lazy"
/>

When the exact pixel size varies (a responsive embed, for example), use CSS instead:

styles/embed.cssaspect-ratio reserves space without fixed pixel dimensions
.video-embed {
  width: 100%;
  aspect-ratio: 16 / 9;
}

2. Give dynamically injected content a fixed-height slot

If a cookie banner, ad slot, or promo bar has to be inserted after the initial render, give its container a reserved min-height from the start instead of letting it push content down when it arrives - even an empty placeholder box prevents the shift.

3. Match your fallback font's metrics to the real font

Use font-display: swap paired with a fallback font whose x-height and average character width are close to your real font (tools like Fontaine or manual size-adjust in an @font-face block can match them), so the swap doesn't visibly reflow the line.

4. Never insert content above the user's current scroll position

If new content has to appear - a "new posts available" banner, for example - insert it below the fold or require a user action to reveal it, rather than injecting it above what's already visible.

How Scanverra Detects CLS Issues

Scanverra runs a real Lighthouse pass against your live URL and reads the actual cumulative-layout-shift value from it - the same run used for LCP and TTFB - and flags a dedicated issue when it's high, with a description tied to why layout instability specifically matters for anything (human or automated) trying to interact with your page.

FAQ

Frequently asked questions

0.1 or below is "good." 0.1 to 0.25 needs improvement, and above 0.25 is "poor." The score is unitless - it's a sum of how far visible elements moved, weighted by how much of the viewport they occupy.

Yes. CLS doesn't care about speed, only distance and area - a lightning-fast shift that moves a large element still adds the same score as a slow one. The only shifts excluded are ones that happen within 500ms of a user interaction like a click or tap.

Local testing on a fast connection often loads ads, fonts, and embeds before you'd notice a shift. Scanverra measures the real render sequence against your live URL, which surfaces shifts that only show up under realistic network timing.

Only if they push existing content down after it's already rendered. A cookie banner that overlays content, or one that's reserved space for from the first paint, doesn't count - one that slides in and shoves the page content downward does.

Free - no sign-up required

Check this on your own site

Run a free scan and see exactly where you stand - no sign-up required.

Run free audit