Performance

Cumulative Layout Shift: A Practical Guide for Fixing Every Cause of CLS

Cumulative Layout Shift CLS cover with the title in gold on black and a sprinter driving off starting blocks against a yellow panel

Cumulative Layout Shift, or CLS, scores how much a page moves around unexpectedly while people load and use it. A good CLS is 0.1 or less. It is the odd one out among Google's three Core Web Vitals: not a time but a unitless number built from how far content jumps and how much of the screen it drags along. It is also the most fixable of the three, because layout shift has a short, known list of causes and every one of them has a direct cure. This post covers how the score is calculated, what counts against you and what does not, then walks that full list, cause by cause, each with its fix and the code to apply it.

The short version

  • Good is 0.1 or less, poor is above 0.25, measured at the 75th percentile of real visits.
  • Every shift scores impact times distance, grouped into session windows; your worst window is the page score.
  • Shifts within 500ms of a click, tap, or key press do not count.
  • The big four causes are unsized images, injected ads and banners, swapping web fonts, and unsized embeds.
  • The single highest-value fix is width and height attributes on every image and video.

Why Google measures layout stability

Everyone has lived the failure this metric exists to punish: you go to tap a button, an ad loads above it, and you buy something or close something you never meant to touch. Loading speed metrics could not see that problem, because a page can render fast and still lurch for ten more seconds as fonts, ads, and embeds pile in. So Google built a metric for visual stability and made it a third of the Core Web Vitals. Unlike its siblings it keeps scoring for the entire visit, not just the load, which is why pages that look calm in a lab test still fail in the field when a promo bar drops in on scroll.

How the CLS score is calculated

Each individual shift scores as impact fraction times distance fraction. Impact is how much of the viewport the moving content touched, before and after the move; distance is how far it traveled as a share of the viewport's longer side. If content covering half the screen drops by a quarter of the viewport height, that one shift scores 0.5 times 0.25, which is 0.125, already past the good threshold on its own.

Shifts then group into session windows: a window collects shifts that happen in quick succession, closes after a one second gap with no shift, and never runs longer than five seconds. Your CLS is the total of the worst single window, not the sum of everything that ever moved. Google switched to this windowed model in 2021 so long-lived pages and infinite scrolls are judged on their worst burst rather than punished forever. The practical reading: one chaotic moment fails a page, and a dozen tiny scattered shifts usually do not.

What counts against you and what does not

Only unexpected movement counts. Shifts within 500 milliseconds of a click, tap, or key press are excluded, because the user asked the page to change; an accordion opening or a filter re-sorting a grid is free. Movement by transform does not count either, since transform paints the element elsewhere without moving its neighbors. What counts is content whose start position changes without the user asking, which is exactly what happens when something above it arrives late and takes up space. That single sentence is the diagnosis for nearly every failing page.

What the 0.1 threshold requires

Good is 0.1 or less, poor is above 0.25, and Google assesses the 75th percentile of real Chrome visits over a rolling 28-day window, mobile and desktop separately. Field data is the scoreboard and lab runs are the debugger, and for CLS the gap between them is wider than for any other metric: Lighthouse watches a few seconds of initial load, while the field number includes everything that shifts when a real person scrolls into lazy-loaded content five minutes in. A page can score 0.01 in the lab and fail in Search Console, and the lab was not wrong, it just went home early.

Every cause of layout shift and its fix

Images and videos without dimensions

The most common cause by far. Without width and height attributes the browser reserves zero space, renders the text, then shoves everything down when the file arrives. The fix is one attribute pair per image: modern browsers use width and height to compute the aspect ratio and hold the space before a single byte downloads. For fluid layouts, CSS aspect-ratio keeps the reserved box proportional at any screen width. This one fix ends the majority of CLS failures we see.

Ads, banners, and promo slots

Ad slots fill late by design, and slots whose size varies per ad are worse. Give every slot a container sized to its largest expected creative before anything loads, and keep the container when the ad fails to fill rather than collapsing it. An empty box is a small aesthetic cost; a page that jumps is a measured one.

Embeds and iframes

Video players, maps, and social embeds arrive with unknown dimensions unless you constrain them. Wrap each one in a container with explicit dimensions or an aspect-ratio matching the content. This site loads video and map embeds behind sized facades for exactly this reason: the space exists in the first paint, and the heavy iframe only loads on interaction.

Web fonts swapping in

When the real font replaces the fallback at a different size, every line of text reflows and the whole column below moves. Preload the main text font, serve it with font-display swap, and then close the remaining gap with fallback metric matching: the size-adjust, ascent-override, and descent-override descriptors tune the fallback font to occupy almost exactly the space the web font will take, so the swap barely registers. Metric-matched fallbacks are the difference between a font strategy that reduces shift and one that removes it.

Content injected above existing content

Cookie notices, signup bars, and countdown strips that push the page down are self-inflicted CLS. Anything that appears without a user action should overlay the page or occupy space reserved in the initial HTML. The same rule applies to client-side personalization that swaps a small element for a bigger one after load.

Late CSS and skeletons that lie

Styles that arrive after first render resize elements already on screen, so inline the critical CSS for above-the-fold layout. The client-side variant of this problem is the skeleton screen built at a different size from the content it stands in for; a placeholder only prevents shift if it is dimensioned like the real thing.

Animating layout properties

Animating width, height, top, or margin moves neighbors on every frame, and each frame can log a shift. Animate transform and opacity instead; both skip layout entirely, run on the compositor, and score nothing.

The fixes in code

<!-- Layout shift: no reserved space -->
<img src="hero.jpg" alt="Product hero">

<!-- Stable: browser reserves the space up front -->
<img src="hero.jpg" alt="Product hero" width="1200" height="600">

/* Responsive containers keep their proportions */
.video-wrap { aspect-ratio: 16 / 9; width: 100%; }

/* Ad slots hold their largest expected size */
.ad-slot { min-height: 250px; width: 300px; contain: layout; }

/* Fonts: swap plus a metric-matched fallback */
@font-face {
  font-family: 'Open Sans';
  src: url('/fonts/opensans.woff2') format('woff2');
  font-display: swap;
}
@font-face {
  font-family: 'Open Sans Fallback';
  src: local('Arial');
  size-adjust: 105%;
  ascent-override: 92%;
}
body { font-family: 'Open Sans', 'Open Sans Fallback', sans-serif; }

How to measure and debug CLS

PageSpeed Insights shows lab and field CLS for any URL, and Search Console reports it site-wide by URL group. For debugging, record a load in the Chrome DevTools Performance panel: each layout shift entry in the timeline names the elements that moved and how far, and the rendering settings can flash shift regions on screen as they happen. Always test with a cleared cache, network throttling, and a mobile viewport, because a warm cache on a fast machine renders everything at once and hides every shift your real visitors experience. Then scroll the whole page, since field CLS counts the shifts that lab loads never reach.

Debugging order that saves time: fix the images first even if the DevTools recording points at something flashier. Unsized media is usually both a shift of its own and the trigger that makes later shifts travel farther, so measurements taken before the image fix routinely misattribute the damage.

What does not fix CLS

  • Making the shift faster. CLS scores distance and area, not duration. A quick jump costs the same as a slow one.
  • Spinners and overlays. A loading spinner that ends with content popping into unreserved space just delays the same shift.
  • Removing lazy loading everywhere. Below-the-fold lazy loading is fine when images carry dimensions; eager loading without them shifts exactly the same.
  • Hiding content until fonts load. Blocking render trades a shift for a blank wait, hurts loading metrics, and still moves if the fallback space was wrong.
  • A perfect lab score. Lighthouse watching a five second load says little about the promo bar that drops in on scroll. Only field data closes the case.

CLS next to the other Core Web Vitals

MetricMeasuresGood thresholdPrimary fix
LCPLoading speed2.5 secondsSpeed up the largest element
INPResponsiveness200 millisecondsStop blocking the main thread
CLSVisual stability0.1Reserve space for everything

Core Web Vitals matter for rankings the honest way: as a tiebreaker-weight page experience signal, not a shortcut past better content. CLS earns its keep in conversions first, because a stable page stops costing you the mis-taps and lost reading positions that never show up in analytics. It is also the cheapest of the three to fix. Image dimensions and sized slots are afternoon work, while Largest Contentful Paint can involve servers and Interaction to Next Paint can demand real refactoring. Start here, bank the win, then take on the harder two.

Where Egochi fits

Egochi audits and fixes Core Web Vitals as part of our technical SEO services: finding the shift sources in your field data, applying the fixes above, and monitoring so regressions get caught early. Stability is easiest when it is designed in, so our web design work builds new sites with reserved space, sized embeds, and metric-matched fonts from the first template. This site is built that way, which you can check in ten seconds with PageSpeed Insights.

Questions people ask about CLS

What is a good CLS score?

A good CLS score is 0.1 or less. Between 0.1 and 0.25 needs improvement, and above 0.25 is poor. Google measures the 75th percentile of real page loads over a rolling 28-day window, so three out of four visits need to land at 0.1 or under to pass.

Does CLS affect SEO rankings?

Yes, modestly. CLS is one of the three Core Web Vitals in Google's page experience signals, which act as a tiebreaker-weight factor. Pages that shift heavily can rank below stable competitors when everything else is close, and Search Console flags the URL groups that need work.

How do I find what is causing layout shift?

Record a page load in the Chrome DevTools Performance panel and click the layout shift entries in the timeline; each one names the elements that moved and how far. Test with a cleared cache and network throttling, because fast cached loads hide the shifts real visitors see.

Do user-initiated actions count toward CLS?

No. Shifts within 500 milliseconds of a click, tap, or key press are excluded, because the user expected the page to respond. Only unexpected movement counts against the score.

Why is my CLS different in lab tools and field data?

Lab tools only watch the initial load. Field data follows real visitors through the whole session, including scrolling into lazy-loaded content and late ads. Google ranks on field data, so trust Search Console over a one-off lab run.

Do animations affect CLS?

Animations that change layout properties like width, height, top, or margin can shift surrounding content and count against CLS. Animations built on transform and opacity do not trigger layout at all, which is why they are the safe default.

Written by , Head of Web Design & Development at Egochi. Every post on this blog comes from the person who runs that work for clients, not a content mill.

Want this handled for you?

Egochi is a US digital marketing agency working with local businesses through enterprise brands from offices in New York, Miami, Milwaukee, and Madison. Tell us what you are trying to grow and we will send back a plan with real numbers in it.

Get a Free Proposal Call (888) 644-7795

Grade Your Website in About 30 Seconds

Egochi's free audit scores any page for technical SEO, content, and AI search readiness. The report renders on screen, and an analyst reviews every run.