CLS layout shift diagram showing images without dimensions and font swap causing content to jump during page load
Web Diagnostics

CLS Layout Shift Explained — What Causes It and How to Fix It

Sunny Pal Singh · · 7 min read

Cumulative Layout Shift is the Core Web Vital that describes the experience of going to click a button just as an ad loads above it and you accidentally click the ad instead. It's measurable visual instability — elements jumping around during page load. A CLS score above 0.25 means your page is genuinely unpleasant to use, and Google uses it as a ranking signal because it correlates directly with user frustration.

Most CLS problems come from a small set of root causes. Images without dimensions, fonts that swap at render time, and ads injected after the page loads account for the majority of CLS issues across the web. The fix in each case is straightforward once you know which cause you're dealing with — but diagnosing the right cause first is the step most guides skip.

Key Takeaways

  • CLS is scored 0–∞; Good = <0.1, Needs Improvement = 0.1–0.25, Poor = >0.25 — lower is better
  • Images without width and height attributes are the single most common CLS cause — the browser doesn't know how much space to reserve
  • Web fonts that swap (FOUT/FOIT) cause text to jump when the custom font loads — use font-display: swap with <link rel="preload"> for the font file
  • Ads, embeds, and dynamically injected content cause CLS when they push existing content down — reserve space with min-height or skeleton placeholders
  • CLS is measured in field data (real users) at P75 — fix the worst offenders first, not just what Lighthouse flags

What CLS Actually Measures

CLS (Cumulative Layout Shift) measures the sum of all unexpected layout shifts during the page's lifetime. A layout shift occurs when a visible element changes position between frames — specifically, when it moves without being triggered by user interaction.

The score is calculated as: shift fraction × impact fraction for each shift, summed together. "Shift fraction" is how much of the viewport the element moved; "impact fraction" is how much of the viewport was affected by the moving element. A large element moving a large distance = high CLS contribution.

CLS ScoreRatingWhat it means
< 0.1GoodPages feel stable during load
0.1 – 0.25Needs ImprovementOccasional visible shifts
> 0.25PoorFrequent, disruptive shifts — ranking impact likely

CLS is a Core Web Vital and part of Google's Page Experience ranking signal. It's measured at the 75th percentile of real user field data — meaning your fastest, most stable users don't determine your score; your worst-performing 25% do.

How to Measure CLS

Lighthouse (Chrome DevTools) — Lab measurement. Shows CLS score and lists the elements that contributed to shifts. Run DevTools → Lighthouse → Performance audit → scroll to Cumulative Layout Shift → click "View original trace" to see exactly which elements shifted and when.

Chrome DevTools — Performance tab — Record a page load and look for pink "Layout Shift" markers in the Experience row. Click each marker to see which element shifted, by how much, and its contribution to the total CLS score.

PageSpeed Insights — Field data from CrUX at P75. Shows real users' CLS experience. If field data is significantly worse than your Lighthouse lab score, you have CLS caused by content that doesn't load in Lighthouse's controlled test environment — typically ads or user-state-dependent content.

Web Vitals Chrome extension — Shows real-time CLS score as you browse the page, including live attribution of which elements are contributing shifts. Useful for catching dynamic CLS that Lighthouse misses.

The Most Common Causes and Fixes

Cause 1: Images Without Width and Height

The most common CLS cause by far. When an <img> tag has no explicit dimensions, the browser allocates zero space until the image downloads, then jumps to the image's natural size — pushing everything below it down.

<!-- CLS cause — no dimensions -->
<img src="hero.jpg" alt="Hero image">

<!-- Fixed — dimensions reserve space before load -->
<img src="hero.jpg" alt="Hero image" width="1200" height="630">

You don't need the exact pixel size — just the correct aspect ratio. The browser uses width and height to calculate the ratio and reserves the right amount of space before the image loads. CSS can still control the displayed size.

The Page Speed Inspector flags images missing width and height attributes directly in its HTML audit — run it to see all affected images on a page at once.

Cause 2: Web Fonts Causing FOUT/FOIT

When a custom font loads after initial render, text reflows to the new font's metrics. Different fonts have different character widths — a heading in Helvetica takes different space than the same heading in Inter. When the font swaps, text reflows and everything shifts.

Fix: use font-display: swap in your @font-face rule, and preload the font file so it's available as early as possible:

<link rel="preload" href="/fonts/inter.woff2" as="font" type="font/woff2" crossorigin>
@font-face {
  font-family: 'Inter';
  src: url('/fonts/inter.woff2') format('woff2');
  font-display: swap;
}

font-display: optional is even better for CLS — the browser uses the fallback font if the custom font isn't available within a very short window, eliminating the swap entirely. Trade-off: the custom font may not show on first page load for users with slow connections.

Cause 3: Ads and Third-Party Embeds

Banner ads, cookie consent banners injected by a CMP, social media embeds, and newsletter overlays all cause CLS when they push content down after the initial render. The pattern: page renders without the ad slot, ad loads 500ms later, everything below the ad jumps down.

Fix: reserve space for the ad before it loads:

.ad-container {
  min-height: 250px; /* Reserve expected ad height */
  width: 100%;
}

For cookie consent banners: use position: fixed or position: sticky so the banner overlays content rather than pushing it. A full-width cookie bar that appears above the fold on first visit is one of the highest-impact CLS sources on modern sites.

Cause 4: Dynamically Injected Content Above Existing Content

Any element injected into the DOM above existing content after the page loads will push that content down — causing CLS. Common sources: notification banners loaded via JavaScript, announcement bars fetched from an API, chat widgets that appear at the top of the viewport, or sticky headers that render late.

Fix: either render these server-side so they're in the initial HTML (no shift), or inject them below the fold where no visible content is displaced. If an element must be injected above the fold, reserve its space in the initial HTML before the JavaScript runs.

Cause 5: CSS Animations Using Layout Properties

CSS animations that change top, left, width, height, or margin trigger layout recalculation on every frame — potentially causing layout shifts. Animations using transform: translate() and opacity run on the compositor thread and don't affect layout at all.

/* Causes CLS — changes layout properties */
@keyframes slide-bad { from { top: -100px; } to { top: 0; } }

/* No CLS — compositor-only properties */
@keyframes slide-good { from { transform: translateY(-100px); } to { transform: translateY(0); } }

CLS From Dynamic Content After User Interaction

Since 2022, Google excludes layout shifts that occur within 500ms of user interaction from the CLS score. This means:

  • A shift caused by clicking "Load more" — not counted
  • A shift triggered by a form submission — not counted
  • Carousels and accordions triggered by user clicks — excluded

This exclusion means your Lighthouse score may not reflect CLS during interactive sessions — Lighthouse only measures passive load-phase shifts. If users report the page feels jumpy while using it but your Lighthouse score looks clean, check for interaction-triggered shifts using the Chrome Performance tab during active interaction.

Diagnosing Field CLS Worse Than Lab

If your PageSpeed Insights field data CLS is significantly worse than your Lighthouse score:

  • Ads that don't load in Lighthouse — Lighthouse blocks many ad networks in its test environment; real users see the ads load and cause shifts
  • Cookie consent banners — CMPs are often blocked by Lighthouse's test URL but trigger for real first-time visitors
  • User-state-dependent content — login banners, personalisation blocks, A/B test variants cause shifts for some users but not in Lighthouse's neutral state
  • Slow network conditions — on slow connections, more elements load after first paint, creating more opportunities for shifts
Note: The Page Speed Inspector checks for images missing width/height attributes as part of its HTML audit — one of the fastest ways to surface the most common CLS cause across a page. For field CLS data, check Google Search Console → Core Web Vitals report, which aggregates real-user CLS at P75 across all your pages.

Priority Order for CLS Fixes

Fix in this order:

  1. Add width/height to all images — highest impact, usually fastest fix; run the Page Speed Inspector to find every affected image
  2. Reserve space for ads and embeds — use min-height on ad containers before the ad loads
  3. Fix font loading — add font-display: swap and preload your primary font files
  4. Move cookie banners to overlay — change from pushing content to overlaying it (position: fixed)
  5. Audit late-injected elements — anything injected above the fold after initial render; either server-render or reserve space

Check Your Page's Core Web Vitals

Free, no signup. The Page Speed Inspector audits your page for images missing dimensions, render-blocking resources, and other CLS-contributing issues — with specific element-level recommendations.

Try the Page Speed Inspector Free →
SP

Sunny Pal Singh

Fellow · Technical Director — AI Infrastructure, Cloud Orchestration & Network Automation

Sunny is a Fellow and Technical Director specialising in AI infrastructure, cloud orchestration, and network automation. With hands-on depth across AWS, Azure, GCP, Red Hat OpenStack, and OpenShift, he leads high-performing teams of architects and engineers building transformative solutions at scale. He built ByteWaveNetwork to bring the same engineering rigour to everyday web tooling.

Affiliate disclosure: Some links on this page may be affiliate links. We only mention tools we've personally used and have an honest opinion about. Affiliate revenue helps keep ByteWaveNetwork's tools free and maintained. We are not paid by any of the tools compared in this article for favorable coverage.

Choose design