Cumulative Layout Shift
Metric
A single accumulated number describing how far elements on a page move out from under a reader without warning while the page is being used.
Why it exists
For a long time, web performance numbers only counted time. How many seconds until something appeared, how many until it could be clicked. But the moment a user gives up on a page doesn't only arrive when things are slow. It also arrives when the sentence being read jumps down the screen, or when a different button slides into the spot the finger was already heading for.
Shifting comes from things that arrive late. Text renders first, an image lands afterward, and only then does the browser clear room for it by pushing everything below further down. Ad slots and notification bars do the same thing. The awkward part is that fast pages produce this more readily than slow ones. Drawing a skeleton first and filling in content later shortens the time to first paint and creates movement in exchange. A metric that only counts seconds can't see that trade.
Pagedeck got a support ticket about exactly this. On the pricing screen, a notice bar dropped in from the top just as someone was about to press the purchase button, the whole page slid down, and what had moved into that spot was the cancel-plan button. Noa reproduced it and found the request fetching the notice arrived 0.4 seconds late on average. The slower the connection, the later it landed and the bigger the jump. Cumulative Layout Shift, usually shortened to CLS, is the number built to catch incidents like that one.
How to calculate it
The score for a single shift is the impact fraction multiplied by the distance fraction. The impact fraction is the share of the screen the moving element covered; the distance fraction is how far it traveled, divided by the longer dimension of the screen.
With numbers: say a block of text occupying half the screen height gets pushed down by a quarter of the screen height. Combine the area it covered before the move with the area it covered after, and that comes to 75 percent of the screen, so the impact fraction is 0.75. It traveled 25 percent of the screen height, so the distance fraction is 0.25. Multiplied, this shift scores 0.1875.
Two rules govern how those scores get added up.
- Sums are taken per window. Rather than totaling every shift across the whole visit, consecutive shifts are grouped into windows of at most five seconds, and the window with the largest sum is the one that counts. A page someone keeps open for an hour doesn't keep climbing for that reason alone.
- Changes the user asked for are excluded. Expanding a "show more" section pushes content down, but that movement was expected. Anything that happens within half a second of a click or keypress is left out of the score.
The value is measured in real users' browsers, so the same page produces different numbers depending on the conditions people arrive under. Where LCP measures the time until the largest piece of content is painted, CLS measures how much the ground moved during that process.
What a good number looks like
0.1 or below is considered good. Above 0.25 is poor, and the range between the two needs work. The 0.1875 from the example above means a single shift is already enough to land a page in the middle band.
The judgment uses the 75th percentile rather than the average. Line up every visitor's value from lowest to highest and take the one three quarters of the way along. Averages let good results from fast devices bury bad ones from slow devices. A page where 75 of 100 users see 0.05 and 25 see 0.4 averages out to 0.14, which looks acceptable, while the percentile reading lands near 0.4 and shows the problem.
Lowering the number almost always means reserving space in advance.
- Give images and videos explicit dimensions. With width and height declared, the browser holds an empty box of the right size before the file arrives. This is why sizing comes up as part of image optimization.
- Reserve room for things that arrive later. An area meant for an ad or a notice bar should keep its height even while it's empty.
- Don't insert anything above content that is already visible. When something has to appear, float it near the bottom of the screen or lay it over what's already there.
How it sounds at work
"CLS jumped from 0.08 to 0.21 in this release. I think it's the new banner."
Shifting has crossed into the poor band, and there's a specific change to suspect.
"Please put width and height on that image, or CLS goes back up."
Without declared dimensions the browser can't reserve the space, and movement follows.
"It's zero locally but real users are seeing 0.3. Looks like it only happens on slow connections."
Lab measurements and field measurements are telling different stories.
At Pagedeck the two people who watch this number are Theo and Noa. Theo keeps it on the pre-release checklist, and Noa marks the place where late-arriving elements will land directly in the mockup while the screen is still being designed. Both habits came out of the notice-bar incident. An empty box drawn in the mockup makes whoever builds it declare a height, and then a late notice doesn't move anything.
The first step in fixing the number is finding what moved. Browser developer tools name each shifted element and show its individual score. Usually one or two elements account for most of the total, so repairing those alone cuts the value by more than half.
What people get wrong
The most common misreading treats CLS as a speed metric. It shows up in the same conversations as web performance, so the assumption is understandable. But it doesn't measure time at all. A page that appears in one second can score 0.4 while a page that takes four seconds scores 0. Splitting content into pieces to shorten load time tends to increase shifting rather than reduce it. Assume the number improved because the page got faster, skip the check, and users end up with a page that appears sooner and gets mis-clicked more often.
Treating a local score of zero as proof is the other common error. Refreshing on a development laptop rarely shows any movement, because the files are cached and the connection is fast enough that nothing arrives late. Field values come from slow connections and older devices, and they include ads and third-party scripts that never load in a development environment. So this number has to be confirmed against real-user data, which is what the Core Web Vitals report — the bundle covering loading, responsiveness, and stability — is there to provide.
Where to go next
- Web performance
see which branch this metric belongs to
- LCP
the same screen viewed from the time side
- Core Web Vitals
see which bundle CLS sits in and how it reaches search ranking
Last updated 2026-09-16