You open an article, start reading the first paragraph, and the text jumps down the screen. An ad has loaded above it. You find your place again, go to tap a link, and at that exact moment an image finishes loading and the link slides out from under your finger. You tap something else entirely.

That experience has a number attached to it. It is called Cumulative Layout Shift, or CLS, and it is one of Google’s three Core Web Vitals, alongside LCP and INP.

The definition

CLS measures unexpected movement of visible page content.

Three words in that sentence are doing real work.

Unexpected: shifts the user did not ask for. If someone clicks “read more” and the page expands, that is expected and does not count.

Visible: only movement inside the viewport is measured. Content rearranging itself far below the fold, where nobody can see it, is not scored.

Movement: specifically, an element that changes position between two rendered frames. An element that simply appears in empty space does not shift anything and scores zero.

The other thing to understand up front is that CLS covers the entire lifetime of the page, not just the load. A shift caused by a lazy-loaded image thirty seconds into a scroll counts exactly as much as one caused by a slow web font at load. This trips up a lot of teams, because most quick performance tests only ever load the page and stop.

How the score is calculated

CLS is unitless. It is not seconds and it is not pixels. Each individual shift gets a score:

layout shift score = impact fraction × distance fraction

The impact fraction is how much of the viewport was affected: the combined area covered by the moving element in its starting position and its ending position, as a share of the viewport.

The distance fraction is how far it moved, as a share of the viewport’s largest dimension.

A worked example makes this concrete. Say a text block fills the top half of the screen, and a banner loads above it, pushing it down by a quarter of the screen height:

  • The block occupied the top 50% and now occupies 25% to 75%. The union of those two areas is 75% of the viewport, so the impact fraction is 0.75.
  • It moved down by 25% of the viewport height, so the distance fraction is 0.25.
  • 0.75 × 0.25 = 0.1875 for that single shift.

One banner, and you have already blown past the “good” threshold.

Session windows

Individual shifts are grouped into session windows. A window opens at the first shift and keeps extending as long as another shift occurs within 1 second, up to a maximum of 5 seconds. Your page’s CLS is the score of the worst single window, not the total of everything that happened.

This matters more than it sounds. A page with one catastrophic burst of movement scores worse than a page with many small, well-spaced shifts. It also means you should not try to fix every shift on the page at once. Find the window that is setting your score and start there.

Scoring thresholds

CLS scoreRating
0 to 0.1Good
0.1 to 0.25Needs improvement
Above 0.25Poor

These have been stable since Core Web Vitals launched, and they are unchanged in 2026, whatever the periodic claims to the contrary in SEO coverage.

Four details about how the threshold is applied in practice:

  1. It is the 75th percentile, not the average. Your page passes when at least 75% of real visits come in at 0.1 or below. A great median score means nothing if the slowest quarter of your traffic is having a terrible time.
  2. Mobile and desktop are assessed separately. Passing on desktop and failing on mobile is a fail where it counts, since mobile is usually the bulk of the traffic.
  3. There is no partial credit. For an overall “good” Core Web Vitals rating a page needs LCP, INP and CLS all in the green. Two out of three is a fail.
  4. It is based on field data. The assessment uses real Chrome users, via the Chrome User Experience Report. A perfect lab score in Lighthouse is a useful diagnostic, not a pass.

What causes layout shifts

Almost every CLS problem comes down to the same root cause: the browser did not know how much space something would need, so it laid out the page without it, then had to redo the work. Here are the usual suspects.

Images and videos without dimensions. The classic. Without width and height attributes (or a CSS aspect-ratio), the browser reserves zero height, lays out everything below, then shoves it all down when the image arrives. Modern browsers compute an aspect ratio automatically from the HTML attributes, but only if you supply them.

Ads, embeds and iframes. Third-party content whose size you do not control, arriving whenever the third party feels like it. Ad slots are the single biggest source of CLS on content sites, and they are worse than images because the size can vary per impression.

Dynamically injected content. Cookie banners, newsletter bars, promo strips, “your session is expiring” notices: anything JavaScript inserts above existing content after the page has already rendered. Injecting content at the top of a page shifts everything below it, which is why a cookie banner can single-handedly fail a site.

Web fonts. A fallback font renders first, then the web font loads and swaps in with different metrics: different character widths, different line heights. Text reflows, and everything below it moves. This is the shift teams most often miss, because it is small, fast, and only shows up on a cold cache.

Animating the wrong properties. Animating top, left, width, height or margin triggers layout and counts as a shift. Animating transform and opacity runs on the compositor, moves nothing in the layout, and scores zero. Same visual effect, completely different metric.

Client-side rendering and hydration. Content that renders after the JavaScript loads, skeleton placeholders that do not match the height of the real content, shared layouts that change height between routes. In single-page apps this is usually the dominant cause, and it is invisible to tools that only measure the initial load.

DOM updates that wait on the network. A button that fetches data and only then expands a panel: if the response takes longer than 500 ms after the click, the resulting shift is no longer attributed to the user interaction and starts counting against you.

What does not count

Useful to know, so you do not waste time chasing them:

  • Shifts within 500 ms of a user interaction are excluded. Accordions, dropdowns, “load more” buttons: all fine, as long as they respond promptly.
  • Compositor-only animations (transform, opacity) do not shift layout.
  • Elements appearing in space that was already reserved for them.

Why it is worth fixing

The SEO argument is real. CLS is part of the page experience signals, and passing all three Core Web Vitals is an advantage on competitive queries. But it is a tiebreaker between comparable pages, not a substitute for the content being good. Anyone promising dramatic ranking gains from a CLS fix alone deserves some scepticism.

The stronger argument is simpler: layout shift makes people mis-click. On a content site that means bounces and accidental ad clicks. On a checkout it means a customer hitting the wrong button on a form they were about to complete. It is one of the few metrics where a bad score maps directly onto a user swearing at their phone.

Where to go next

Now that you know what the number means, there are two things to do with it.

Measure it properly, using field data rather than a single lab run. Search Console, PageSpeed Insights and Chrome DevTools each answer a different question, and they will disagree with each other for good reasons. See how to measure CLS.

Then fix it. The guide to optimizing CLS: 8 concrete fixes walks through the remedy for each of the causes above: reserving space for images and ads, taming injected banners, and getting fonts to swap without reflow, with CLS put in the context of LCP and INP.