Seo Aug 10, 2026 5 min read

Cumulative Layout Shift: Why It Happens and How to Kill It

Cumulative layout shift how to fix it: real causes, code fixes, and testing steps to stop content jumping and improve your Core Web Vitals score.

Cumulative Layout Shift (CLS) is the Core Web Vital that measures visual stability — how much your page's content jumps around while it loads. A bad CLS score doesn't just hurt your Google rankings; it actively annoys users who try to tap a button only to have it move right before their finger lands. This post walks through the actual causes of layout shift and the concrete fixes for each one.

What Counts as a "Shift" (and What Doesn't)

CLS only counts unexpected layout shifts — movement that happens without user interaction, or more than 500ms after a click/tap. Things like:

  • An image loading in and pushing text downward
  • An ad slot resizing after the ad network responds
  • A cookie banner appearing and shoving the page content
  • A custom font loading and reflowing text (FOIT/FOUT)
  • Content injected above existing content via JavaScript

Google scores "Good" CLS as under 0.1, "Needs Improvement" between 0.1–0.25, and "Poor" above 0.25. You can check your current score in PageSpeed Insights, Chrome DevTools' Performance panel, or the Core Web Vitals report in Search Console.

Fix #1: Reserve Space for Images and Videos

This is the single most common cause of CLS, and the easiest to fix. If an image has no defined dimensions, the browser doesn't know how much space to allocate for it — so it renders at zero height, then jumps once the image loads.

The fix

  • Always set width and height attributes on <img> tags, even if you're using CSS to control final size.
  • Use the aspect-ratio CSS property as a fallback for responsive images: img { aspect-ratio: 16 / 9; width: 100%; }
  • For background-loaded or lazy images, wrap them in a container with a fixed min-height until the image resolves.
<img src="hero.jpg" width="1200" height="600" alt="Hero image" loading="lazy">

Modern browsers use the width/height ratio to auto-calculate an aspect ratio box before the image even downloads, which eliminates the shift entirely.

Fix #2: Stop Ads and Embeds From Resizing Mid-Load

Ad networks are notorious for this — a slot loads, then the actual ad comes back with different dimensions and everything below it jumps.

  • Set explicit min-height on ad containers based on your most common ad size.
  • Use contain-intrinsic-size combined with content-visibility: auto for below-the-fold ad slots.
  • For iframes (YouTube embeds, social widgets), always specify width/height or wrap in a responsive container with a fixed padding-based aspect ratio trick.
.embed-container {
  position: relative;
  padding-bottom: 56.25%; /* 16:9 */
  height: 0;
}
.embed-container iframe {
  position: absolute;
  top: 0; left: 0;
  width: 100%; height: 100%;
}

Fix #3: Handle Web Fonts Without the Jump

Custom fonts cause layout shift when the fallback font renders first, then swaps to the custom font with different metrics (different character widths, line heights).

Options, ranked by effectiveness

  1. Preload your font files: <link rel="preload" href="/fonts/main.woff2" as="font" type="font/woff2" crossorigin>
  2. Use font-display: optional if a slight delay in showing text is acceptable — this avoids the swap entirely by giving up on the custom font if it's not ready fast enough.
  3. Match fallback font metrics using tools like Fontaine or manual size-adjust/ascent-override CSS descriptors so the fallback occupies nearly identical space to the final font.
  4. Self-host fonts instead of pulling from third-party CDNs — it removes a DNS/connection delay that widens the window where shift can happen.

Fix #4: Never Inject Content Above Existing Content

Banners, cookie notices, "subscribe" bars, and dynamically loaded promo blocks are common offenders when they're injected at the top of the page after initial render.

  • Reserve a fixed-height placeholder in the DOM before the banner script runs, even if it's empty initially.
  • Prefer inserting new content below the fold, or use position: fixed/sticky overlays instead of pushing content down.
  • If you must inject above-the-fold content, do it before the user has had a chance to start reading — ideally before first paint, using server-side rendering or a synchronous inline script.

Fix #5: Animate With Transform, Not Layout Properties

Animations that change top, left, width, height, or margin trigger layout recalculation and count toward CLS if they shift other elements. Animations using transform and opacity don't affect layout at all — they're composited on the GPU.

/* Avoid */
.card:hover { margin-top: -10px; }

/* Use instead */
.card:hover { transform: translateY(-10px); }

A Practical Debugging Workflow

  1. Run the page through PageSpeed Insights or Lighthouse and note the CLS score plus which elements are flagged as shift culprits.
  2. Open Chrome DevTools → Performance panel → record a page load → look for red "Layout Shift" markers in the timeline and click into them to see the exact element.
  3. Check whether custom meta viewport settings or third-party scripts are contributing — an incomplete or misconfigured <meta name="viewport"> tag can cause rendering inconsistencies across devices that compound shift issues. Running your page through AXOX Hub's Meta Tag Analyzer is a fast way to confirm your viewport and other head tags are set up correctly before you go chasing more complex CSS causes.
  4. Fix the highest-impact element first — usually the largest above-the-fold image or the first ad slot.
  5. Re-test after every single fix. CLS issues compound, so fixing one shift can sometimes reveal a second one that was previously masked.

Common Mistakes That Make CLS Worse

  • Using percentage-based heights on containers that hold dynamically-sized content — this doesn't reserve real space until the content loads.
  • Lazy-loading above-the-fold images — lazy loading should only apply to images below the initial viewport; applying it above the fold delays rendering and can trigger shift.
  • Loading multiple third-party scripts synchronously in the <head>, each capable of injecting DOM elements at unpredictable times.
  • Forgetting mobile viewports — a layout that's stable on desktop can still shift badly on smaller screens where ad units and images take up proportionally more space.

Once you've patched the obvious offenders, run your page through AXOX Hub's free Meta Tag Analyzer to double-check your viewport and rendering-related meta tags aren't quietly undermining the layout work you just did.

Try the free tool

Open Tool