Lightscore

Cumulative Layout Shift (CLS)

Cumulative Layout Shift scores how much visible content moves unexpectedly while a page is open. It has no unit. A good CLS is 0.1 or less, at the 75th percentile of page loads.

It's the one Core Web VitalGoogle’s three headline UX metrics: LCP (load), INP (responsiveness), CLS (stability). that measures annoyance instead of speed. A page can load in 800 ms and still be miserable, because the link you aimed at slid down the screen first.

The name is also misleading. CLS is no longer a running total, and that changes how you fix it.

The thresholds

CLS Verdict
0.1 or less Good
0.1 to 0.25 Needs improvement
More than 0.25 Poor

Measure at the 75th percentile of page loads, and segment mobile and desktop separately. The two layouts break in different places.

How is CLS calculated?

A layout shift happens when a visible element changes position between two rendered frames. The browser scores each one:

layout shift score = impact fraction × distance fraction

Google's worked example gives an impact fraction of 0.75 and a distance fraction of 0.25. That is a layout shift score of 0.1875. So the number is a fraction of your screen, not a duration — which is why a CLS has no unit to put after it.

CLS is not cumulative

The original metric added up every shift for the whole life of the page. An infinite scroller could not win. Google revised the definition, and it reached Chrome's web tooling on 2 June 2021.

The browser now groups shifts into session windows. A window opens at the first shift and keeps extending while each gap stays under 1 second. No window runs longer than 5 seconds. CLS is the score of the worst window — not the total.

yes

no

A visible element moves
between two frames

Within 500 ms
of user input?

Expected.
Not counted.

Scored, then grouped
into a session window

CLS = the highest
window score

How a single element movement becomes your CLS. The worst window wins; the rest are not added to it.

That is a different repair job than the name suggests. Find the single worst burst and remove it. Ten small shifts spread across a long article can cost you nothing, while one banner that pushes the body down costs you everything.

Which shifts count?

Only the unexpected ones. A shift within 500 milliseconds of a tap, click or key press carries the hadRecentInput flag, and it's excluded. Opening an accordion is free. The same movement with nobody touching anything is scored against you.

What causes layout shift?

Cause Fix
Images and videos with no dimensions Set width and height attributes, or reserve the box with CSS aspect-ratio
Ads, embeds and late-loaded content Reserve the space in the first layout, or overlay it outside the document flow
Web fonts swapping in font-display: optional, preload the file, and match the fallback metrics
Animated top, left or box-shadow Animate transform instead

Images are the usual culprit, and the cheapest to fix. Modern browsers derive a default aspect ratio from the width and height attributes. The box is then reserved before a single byte of the image arrives.

Why is my CLS 0 in Lighthouse but bad in Search Console?

Because a lab run only sees part of the problem. Google is blunt about it. Lab tools load a page in a synthetic environment. They can only measure the layout shifts that happen during load. Real visitors keep the page open, and CLS keeps counting for the whole life of that page.

We can put a number on how little that leaves. Our three warm example report pages each keep the last 25 audits. Between 3 July and 13 August 2026 that's 131 completed mobile runs, all on Lighthouse 12.8.2, from Frankfurt and Washington. CLS was exactly 0 in 110 of them. The worst value in the whole set is 0.002, about fifty times below the "good" threshold.

The slowest page on that rig makes the point on its own. vercel.com, 6 August 2026, measured from both regions: an LCP of 12.0 seconds from Frankfurt and 13.0 from Washington, for performance scores of 31 and 33. Its CLS was 0 from both.

So we'll say it plainly: a lab CLS is the least informative number in a Lighthouse report. It's worth 25 of the 100 performance points, level with LCPTime until the largest thing in view (hero image, headline) has painted.. Every one of those 131 runs took the full 25, including the page that scored 31. Read a lab CLS of 0 as "nothing moved during load". Never read it as "this page is stable".

The field number is the one Google grades you on. It reaches you through the Chrome UX Report and Search Console, over a rolling 28-day window. So a CLS fix you ship today needs about four weeks to reach full weight there.

What a Lightscore result gives you

Every completed result carries a cls value taken straight from the Lighthouse audit, next to lcp_ms, tbt_ms and the rest. We also hand back the raw Lighthouse JSON. That's where the useful part is. The layout-shifts audit names each element that moved, with its own score.

That 0.002 worst case was a wikipedia.org run, and the JSON splits it across exactly two elements: img.central-featured-logo at 0.00165 and a div.styled-select in the search form at 0.00037. That's the level a fix starts at — a selector, not a number.

We can't give you a field CLS, and no lab tool can. A pinned lab run is good for one thing here: it catches a shift you just shipped, before your visitors meet it. A lab CLS pinned at 0 across many runs is at least a stable baseline. The performance score around it wanders by a few points on its own. So if CLS moves from 0 to 0.3 between two runs of the same version, your layout changed, and the JSON names what moved.

what’s this

The small set of field metrics Google treats as a ranking input and reports in Search Console. We measure their lab equivalents here — real-user field data (CrUX) is a separate signal. TBT is the lab stand-in for INP, not a Core Web Vital itself.

Common questions