Glossary

How Cumulative Layout Shift Is Actually Calculated

Taras Shynkarenko
Taras Shynkarenko
Updated: 7 min read
How Cumulative Layout Shift Is Actually CalculatedHow Cumulative Layout Shift Is Actually Calculated

TL;DR, Quick Answer

7 min read

Cumulative Layout Shift scores each unexpected movement as impact fraction multiplied by distance fraction. The browser groups shifts into session windows that close after a 1 second gap or 5 seconds of total duration, and reports the highest-scoring window as the page's CLS. Nothing is summed across the whole page, which is why the name misleads almost everyone who reads it.

What is Cumulative Layout Shift (CLS)?

Chrome measures Cumulative Layout Shift as the largest burst of unexpected layout movement during a page's lifetime, where each individual shift scores impact fraction multiplied by distance fraction and the highest-scoring burst becomes the page's CLS. The metric exists because content that jumps under a reader's finger costs them the tap they were about to make. Two numbers decide every score: how much of the viewport moved, and how far it went.

The name causes most of the confusion. "Cumulative" describes what happens inside one burst, not across the page, so forty small shifts spread over three minutes can score better than two shifts half a second apart.

How is a layout shift score calculated?

The formula published by the Chrome team on web.dev, checked on 8 September 2026, is a single multiplication:

layout shift score = impact fraction × distance fraction

The impact fraction is the union of the visible area an unstable element occupied in the previous frame and the area it occupies in the current frame, divided by the total viewport area. The distance fraction is the greatest horizontal or vertical distance any unstable element moved in that frame, divided by the viewport's largest dimension, width or height, whichever is greater.

Work one shift end to end. Take a mobile viewport 400px wide and 800px tall, so the largest dimension is 800px. A full-width article heading and its opening paragraph occupy the top 400px, which is half the viewport. A consent banner then injects above them and pushes the block down by 160px.

InputValueWhere it comes from
Viewport400 × 800 px320,000 px total area
Element before the shifty 0 to 400160,000 px visible
Element after the shifty 160 to 560160,000 px visible
Union of both framesy 0 to 560224,000 px
Impact fraction0.7224,000 ÷ 320,000
Distance moved160 pxbanner height
Distance fraction0.2160 ÷ 800

0.7 × 0.2 = 0.14

One banner produced 0.14, which already sits in the "needs improvement" band. The two fractions gate each other: a tiny element scores low even when it travels the full screen, and a full-viewport block scores high even when it travels 20px.

Why is CLS not the sum of every shift?

CLS reports the single highest-scoring session window, not a running total. A session window opens at the first shift and stays open while shifts keep arriving less than 1 second apart, up to a maximum window duration of 5 seconds. When a gap of 1 second or more passes, or the window hits 5 seconds, that window closes and the next shift starts a fresh one. The browser scores each window separately and reports the largest.

Continue the example above. The 0.14 banner shift lands at 1.2s. A web font swaps at 1.5s and reflows a paragraph for 0.03. The gap is 300ms, so both belong to one window worth 0.17. A lazy-loaded embed then shifts the footer by 0.05 at 4.0s, which is 2.5 seconds after the last shift, so it opens its own window.

WindowShiftsWindow score
1 (1.2s to 1.5s)0.14 banner, 0.03 font swap0.17
2 (4.0s)0.05 embed0.05

The page's CLS is 0.17, the larger of the two, not 0.22. Chasing the sum sends teams to the wrong shift: find the window that scored highest and fix what is inside it.

How a session window decides the score
1
First shift fires. The banner push at 1.2s opens a session window and scores 0.14.
2
Next shift lands within 1 second. The font swap at 1.5s joins the same window, pushing its total to 0.17.
3
A gap of 1 second or more passes. The window closes, as it does 2.5 seconds after the font swap.
4
The next shift starts a fresh window. The embed shift at 4.0s opens its own window and scores 0.05.
5
Chrome reports the largest window. 0.17 becomes the page's CLS, not the 0.22 sum of both windows.
The same three shifts score 0.17 as separate session windows, not 0.22 as a running total.

What counts as an unexpected layout shift?

A shift counts as unexpected unless it follows a user interaction within 500 milliseconds. Chrome flags any shift that occurred close behind a tap, click or key press with hadRecentInput, and those shifts are excluded from the score, because a reader who opened an accordion expects the content below it to move.

That 500ms rule is a design lever, not an implementation detail. A "Load more" button costs nothing, and the same content injected by a timer costs whatever the formula says.

A cookie consent banner sliding in above a page on a phone, the kind of injected notice that pushes content down and causes a layout shift.

What causes Cumulative Layout Shift?

Four sources produce almost every shift worth fixing, and each has a fix that removes the shift instead of shrinking it.

Flowsery
Flowsery

Start FREE Trial

Real-time dashboard

Goal tracking

Cookie-free tracking

CauseWhat the browser doesFix
Images and video without dimensionsReserves zero height, then reflows when the file arrivesSet width and height attributes, or reserve the box with CSS aspect-ratio
Ads, iframes and third-party embedsSizes the slot only after the third party respondsReserve the slot with min-height or aspect-ratio, sized from the dimensions that slot has served before
Injected banners, notices and skeletonsInserts a node into the document flow and pushes everything below itReserve the space up front, render it outside the flow as an overlay, or insert it behind a user action
Web fontsSwaps a fallback face for the web font, changing text metrics mid-renderUse font-display: optional, match the fallback with size-adjust and the font override descriptors, and preload the critical face

The pattern underneath all four: reserve the box before the content exists. A browser that already knows the height of a slot has nothing to reflow when the slot fills.

Why does lab CLS differ from field CLS?

Lab CLS covers page load only, and field CLS covers the entire page lifecycle. Lighthouse loads a URL on a fixed device profile, records shifts inside its measurement window, then stops. Real people scroll past that window, trigger lazy-loaded images, dismiss a banner, open a menu, and every shift after Lighthouse's cutoff still counts in the field.

Viewport and network add a second gap. The distance fraction divides by the viewport's largest dimension, so the same 160px banner scores differently on a phone than on a desktop, and a fast lab connection delivers a slot's contents before the shift happens at all, hiding a defect that fires every time on a slow network. Fix regressions in the lab, then judge the result on field data from real visits, where the thresholds for all three vitals sit in one table.

A person scrolling a webpage on their phone outdoors, the kind of real session a session recording captures when a page jumps.

How do you find the shift that caused a bad CLS?

Pair the field score with a recording of the session that produced it, so the burst becomes something you watch instead of something you infer. A p75 of 0.28 tells you the page fails; it does not tell you that a consent banner injects 160px above the fold for visitors whose IP resolves to the EU.

Flowsery ships one script under 10 KB, cookie-free and EU-hosted, and applies no sampling, so the score comes from every session instead of a subset. It records the sessions alongside the timings, groups matching ones into a single issue ranked by how many users hit it, and sends that issue to Slack, Linear or Jira with the replay and steps to reproduce attached.

CLS is one of three Core Web Vitals, and each fails for its own reasons. Largest Contentful Paint covers render timing, Interaction to Next Paint covers responsiveness, and the Core Web Vitals overview explains why a page has to pass all three at once.

Frequently asked questions

What is a good CLS score?

0.1 or less at the 75th percentile is good, 0.1 to 0.25 needs improvement, and above 0.25 is poor, per the Chrome team's thresholds on web.dev as of September 2026. The percentile is calculated separately for mobile and desktop, so a page can pass on desktop and fail on phones. What counts as a good CLS breaks down how the p75 is assembled.

Does CLS have a unit?

No. Both inputs to the formula are fractions of the viewport, so multiplying them produces a unitless number. That is why 0.1 means the same thing on a 400px phone and a 2560px monitor: the metric normalises against the screen it happened on.

Do shifts below the fold count toward CLS?

Only movement of content visible in the viewport at the time of the shift contributes to the impact fraction. An element that reflows 4000px down the page while the reader sits at the top adds nothing. It starts counting the moment the reader scrolls it into view and it moves again.

Why did my CLS get worse after I added a skeleton loader?

A skeleton that does not match the final content's height shifts the page twice instead of once: first when the skeleton appears, then again when the real content replaces it with different dimensions. Size the skeleton to the box the content will occupy, or the placeholder becomes the defect.

Can an animation cause a layout shift?

Animating properties that trigger layout, such as top, left, width or height, moves surrounding content and scores as a shift. Animating transform does not, because the compositor moves the painted layer without re-running layout. Move animations to transform and opacity and the shifts disappear.

Does CLS still accumulate after the page finishes loading?

Yes. The browser watches for shifts through the whole page lifecycle, so a banner that injects 30 seconds in, or an image that lazy-loads on scroll, opens a new session window and can become the page's reported score. This is the main reason a clean Lighthouse run coexists with a failing field score.

How long does a CLS session window stay open?

A session window opens at the first shift and keeps collecting shifts that land less than 1 second apart, up to a hard cap of 5 seconds. A gap of 1 second or a total duration of 5 seconds closes it, and the next shift starts a new window. Chrome scores every window on the page and reports only the highest one as CLS.

Does clicking a button before a shift stop it from counting toward CLS?

A shift is excluded from CLS if it happens within 500 milliseconds of a tap, click or key press, a flag Chrome records as hadRecentInput. A "Load more" button that expands content right after a click costs nothing, while the same content injected by a timer scores under the formula. The rule exists because a reader who just opened an accordion expects what sits below it to move.

Flowsery
Flowsery

Start FREE Trial

Real-time dashboard

Goal tracking

Cookie-free tracking

Why does the same layout shift score differently on mobile than on desktop?

The distance fraction divides how far an element moved by the viewport's largest dimension, so a fixed pixel shift is a bigger fraction of a phone screen than a wider desktop one. The 160px banner push in the walkthrough above scores 0.2 on an 800px-tall viewport and would score lower on a taller desktop screen. Field CLS compounds this by calculating the p75 separately for mobile and desktop, so the same defect can pass on one and fail on the other.

Set width and height attributes on images and video, or reserve the box with the CSS aspect-ratio property, so the browser holds the space before the file arrives. Images without dimensions reserve zero height by default, then reflow the page the moment the file loads. Reserving the box removes the shift instead of just shrinking it.

Was This Article Helpful?

Let us know what you think!

See us more often in Google

One click marks Flowsery as a preferred source, so our articles sit higher in your Top Stories, AI Mode, and AI Overviews.

Before you go...

Flowsery

Flowsery

Revenue-first analytics for your website

Track every visitor, source, and conversion in real time. Simple, powerful, and cookie-free.

Real-time dashboard

Goal tracking

Cookie-free tracking

Related Glossary Terms

Related Articles