SSL Checker DMARC Meta Tags Site Speed Broken Links AI Chat Bookings Try ModusOp

Published 27 April 2026

Cumulative Layout Shift (CLS) measures how much visible content shifts position during page load. Every time something on the page jumps — an image loads and pushes text down, an ad appears mid-scroll, a banner slides in from the top — CLS goes up. The threshold for "good" is under 0.1; "needs improvement" is 0.1 to 0.25; over 0.25 is poor.

CLS is the most fixable Core Web Vital because the causes are mechanical and well-understood. There are about six recurring patterns that cause shifts; this guide covers each one and the specific fix.

What CLS Actually Measures

The browser tracks every layout shift during page load — defined as any element moving from one frame to the next without user input. For each shift, it computes:

Individual scores are summed within "session windows" (5-second windows of activity), and the page's CLS is the maximum session window score during the entire visit.

Key point: shifts caused by user input (clicking a button, typing, scrolling) don't count. Only unexpected shifts.

Cause 1: Images Without Dimensions

The most common cause. An <img> tag without explicit width and height attributes (or CSS dimensions) takes up zero space until it loads — at which point the browser reflows everything below it.

The fix is to set explicit dimensions on every image:

<img src="hero.jpg" width="1200" height="630" alt="...">

Modern browsers use the width:height ratio to reserve space at the correct aspect ratio even before the image loads. As long as you set width and height (the values can be any units; browsers compute the ratio), there's no shift when the image arrives.

For responsive images:

<img src="hero.jpg" width="1200" height="630" style="width: 100%; height: auto;" alt="...">

The HTML attributes establish the aspect ratio; the CSS lets the actual display size adapt to container width.

Cause 2: Web Fonts

Custom web fonts cause "FOIT" (Flash of Invisible Text) or "FOUT" (Flash of Unstyled Text) — depending on settings, the browser either shows nothing until the font loads, or shows a fallback font that gets swapped when the custom font arrives. Both produce layout shifts as the text re-flows at different metrics.

Fixes:

Cause 3: Ads, Embeds, Iframes Without Reserved Space

Display ads and third-party embeds load asynchronously, often hundreds of milliseconds after page render. If you don't reserve space for them, they push content down when they arrive.

The fix is to define a fixed-size container:

.ad-slot {
    min-height: 250px; /* matches the ad's known height */
    width: 100%;
}

For ads that come in multiple sizes, reserve space for the largest possible variant. The visible empty space before the ad loads is less painful than the layout shift after it loads.

For YouTube embeds, social media embeds, and other iframes — set explicit dimensions or aspect-ratio:

iframe {
    aspect-ratio: 16 / 9;
    width: 100%;
    height: auto;
}

Cause 4: Dynamically Injected Content

JavaScript injects content above existing content — banner ads, "subscribe" prompts, GDPR cookie banners, sticky headers, A/B test variants. Every injection causes content below to shift.

Solutions:

Cause 5: Network Race Conditions

Sometimes content loads in unexpected orders. The CSS arrives, layout is computed, then a stylesheet that arrives later changes everything. Or a JS framework hydrates the page after initial render and reflows content differently.

For SPAs with hydration mismatches:

For CSS:

Cause 6: Animations and Transitions

Animations using top, left, width, height, margin, padding trigger layout reflows on every frame — and if they happen during page load, they count toward CLS.

Use only properties that don't trigger layout: transform (for position) and opacity (for visibility). Modern animations should use:

.slide-in {
    transform: translateX(-100px);
    transition: transform 0.3s;
}
.slide-in.active {
    transform: translateX(0);
}

Not:

.slide-in {
    left: -100px;
    transition: left 0.3s; /* triggers layout shift */
}

The Diagnostic Workflow

  1. Run Site Speed Check for an instant CLS measurement.
  2. Use Chrome DevTools Performance Insights tab — it visually highlights every layout shift event and identifies the elements that moved.
  3. Lighthouse reports CLS along with diagnostics for the most impactful shifts.
  4. PageSpeed Insights field data shows real-user CLS — what Google actually measures for ranking.

The Production Habit

For new pages and components:

None of these are difficult; they're disciplines applied consistently. Audit existing pages with Site Speed Check and fix the patterns that recur. Most sites can move from a CLS of 0.3+ to under 0.1 with a few hours of focused work.

Why CLS Matters Beyond Rankings

CLS is annoying. Mis-clicking the wrong button because the page shifted, losing your scroll position because content was injected above, having to re-find your place in an article — these are real user frustrations. Google measuring CLS is a proxy for measuring user-experience pain. The same fixes that improve your rankings improve your conversion rate, your bounce rate, and your real users' experience.

Run any URL through Site Speed Check and the CLS number tells you in seconds what kind of user experience you're delivering. Anything over 0.1 has fixes that pay off in both rankings and visitor sanity.

Measure your CLS

Site Speed Check reports CLS, LCP, INP and the rest — with element-level diagnostics for what's shifting.

Run a Speed Test →