CLS Explained: Cumulative Layout Shift
A page can load quickly and still feel broken. You start reading, an image appears, the text suddenly moves downward, and the button you were about to click jumps somewhere else. That instability is what Cumulative Layout Shift (CLS) is designed to measure.
CLS is one of Google's three Core Web Vitals, alongside Largest Contentful Paint (LCP) and Interaction to Next Paint (INP). Unlike those metrics, CLS is not measured in milliseconds. It produces a unitless score that represents how much visible content moved unexpectedly and how significant that movement was. (web.dev)
What Is CLS?
Cumulative Layout Shift measures the visual stability of a web page by quantifying unexpected movement of visible content.
A layout shift occurs when a visible element changes its starting position between two rendered frames. CLS then groups unexpected shifts into short bursts called session windows and reports the session window with the largest combined shift score. (web.dev)
A practical example is an article where the browser initially renders the headline and text, then an image without reserved dimensions loads above them. The image takes up space, pushes the article downward, and forces the reader to find their place again.
That movement contributes to CLS.
CLS Score
Google's current thresholds are:
| CLS | Assessment |
|---|---|
| 0.10 or lower | Good |
| Above 0.10 to 0.25 | Needs improvement |
| Above 0.25 | Poor |
For Core Web Vitals evaluation, Google recommends looking at the 75th percentile of page visits, segmented between mobile and desktop. In practical terms, at least 75% of visits should experience a CLS of 0.10 or lower.
CLS is unitless. A score of 0.1 does not mean 0.1 seconds. It represents the combined severity of unexpected visual movement.
Why CLS Matters
Layout instability directly affects usability.
A shift can make someone lose their reading position, cause a form control to move while they are interacting with it, or make a user accidentally click a different button from the one they intended. The problem becomes especially noticeable on slower networks, where images, advertisements, fonts, API responses, and third-party content may arrive later than they do during local development. (web.dev)
CLS also matters to search performance. Google documents Core Web Vitals as signals used by its ranking systems and recommends achieving good Core Web Vitals for Search and user experience. However, a good CLS score does not guarantee higher rankings. Google evaluates many signals, and Core Web Vitals are only one part of page experience. (developers.google.com)
INTERNAL LINK: Core Web Vitals Explained
How CLS Works
CLS starts with individual layout shift scores.
For every relevant shift, the browser evaluates two factors:
layout shift score = impact fraction × distance fraction
The impact fraction represents how much of the viewport is affected by unstable elements before and after the movement.
The distance fraction measures how far the most displaced unstable element moved relative to the viewport's largest dimension. (web.dev)
Suppose a moving element affects 75% of the viewport and moves a distance equivalent to 25% of the viewport's largest dimension:
0.75 × 0.25 = 0.1875
The layout shift score for that event is therefore 0.1875.
Session Windows
Modern CLS does not simply add every layout shift that occurs throughout a page's lifetime.
Individual unexpected shifts are grouped into session windows. A session window contains shifts separated by less than one second and can last for a maximum of five seconds.
The page's CLS is the combined score of the largest session window. (web.dev)
This approach prevents long-lived pages such as single-page applications and infinite-scroll interfaces from being automatically penalized simply because users keep them open longer.
Expected Shifts
Not every movement contributes to CLS.
A shift caused directly by a discrete user interaction—such as a click, tap, or keypress—can be excluded when it happens within 500 milliseconds of that interaction. The Layout Instability API exposes this through the hadRecentInput property. (web.dev)
For example, expanding an accordion immediately after a user clicks it is generally expected.
However, scrolling is different. Continuous interactions such as scrolling are not treated in the same way. If lazy-loaded content suddenly pushes existing content downward while the user scrolls, that movement can still contribute to CLS.
Common CLS Causes
The most frequent causes are surprisingly ordinary.
Unsized Images
An image without known dimensions can initially occupy little or no layout space. Once the image loads, the browser discovers its size and moves surrounding content.
Reserve the required space using HTML dimensions:
<img
src="product.jpg"
width="1200"
height="800"
alt="Product"
>
Responsive CSS can still resize the image:
img {
width: 100%;
height: auto;
}
Modern browsers can use the width and height attributes to determine the image's aspect ratio before the image finishes loading. (web.dev)
Ads and Embeds
Advertisements, video embeds, maps, social widgets, and iframes often load after the surrounding page.
If their container initially has no height, everything below it may move when the content appears.
Reserve predictable space:
.video-wrapper {
aspect-ratio: 16 / 9;
}
For variable-height content, a suitable min-height or placeholder can reduce movement. Removing reserved space when no advertisement appears can itself create another layout shift, so placeholders need to be designed carefully. (web.dev)
Dynamic Content
Cookie notices, promotional banners, alerts, recommendations, and asynchronously loaded components can cause large shifts when inserted above content the user is already viewing.
Prefer reserving space beforehand or, where appropriate, displaying the component as an overlay rather than inserting it into the document flow.
Web Fonts
A fallback font and the final web font can have different character widths, line heights, or metrics. When the real font arrives, text may wrap differently and move surrounding content.
Possible improvements include selecting a closer fallback font, loading critical fonts earlier, using font-display appropriately, and adjusting fallback font metrics with properties such as size-adjust, ascent-override, descent-override, and line-gap-override. (web.dev)
Layout-Based Animations
Animating properties such as top, left, width, or height can change layout.
Where possible, use compositor-friendly transforms:
.card {
transform: translateY(20px);
}
instead of repeatedly changing:
.card {
top: 20px;
}
Using transform: translate() or transform: scale() can visually move elements without creating the same type of layout shift. (web.dev)
How to Measure CLS
Start with field data.
Chrome UX Report (CrUX) contains aggregated real-user Core Web Vitals data, including CLS. PageSpeed Insights can display CrUX field data where sufficient data is available, while Search Console groups pages through its Core Web Vitals report. CrUX reports CLS at the 75th percentile and treats CLS as a unitless metric. (developer.chrome.com)
Then use lab tools to investigate the problem.
Chrome DevTools' Performance panel exposes individual layout shifts and groups them into clusters. You can inspect shift scores, affected elements, timing, screenshots, and potential culprits. Chrome's Rendering tools can also highlight layout-shift regions visually. (developer.chrome.com)
A useful workflow is:
Field CLS is poor → reproduce the page → identify the largest shift cluster → inspect the shifted elements → locate the element that caused the movement → fix it → measure again.
Do not assume the element that moved is the root cause. A paragraph may move because an advertisement, image, banner, or another component above it changed size. (web.dev)
Lab vs Field CLS
One common debugging mistake is expecting Lighthouse and real-user CLS to match exactly.
They measure different situations.
A normal Lighthouse test primarily observes the initial page load. Real users may continue scrolling, opening menus, loading more products, triggering route changes, or keeping a page open for several minutes. Unexpected shifts happening later can therefore appear in CrUX even when a simple Lighthouse load looks stable. (web.dev)
When lab CLS is low but field CLS is high, investigate post-load interactions and scrolling behavior.
INTERNAL LINK: Lab Data vs Field Data
CLS Debugging
For difficult cases, Chromium exposes layout shifts through the Layout Instability API:
new PerformanceObserver((entryList) => {
for (const entry of entryList.getEntries()) {
if (!entry.hadRecentInput) {
console.log('Layout shift:', entry.value, entry.sources);
}
}
}).observe({
type: 'layout-shift',
buffered: true
});
This is useful for debugging individual shifts, but it is not a complete implementation of the CLS metric. Correct CLS calculation requires grouping shifts into session windows and handling additional lifecycle cases. For production Real User Monitoring, the web-vitals library is generally safer than reimplementing the complete metric yourself. (web.dev)
Common Misconceptions
“CLS measures loading speed.” No. CLS measures visual stability. A page can load quickly and still have terrible CLS.
“Any movement increases CLS.” No. CLS focuses on unexpected layout shifts. Some shifts associated closely with discrete user input are excluded.
“A Lighthouse CLS of zero means users see zero CLS.” Not necessarily. Post-load shifts may appear in field data but never occur during a simple synthetic page-load test.
“The shifted element caused the problem.” Not always. It may simply have been pushed by another element.
SeoNest Recommendation
Treat CLS as a layout architecture problem rather than a score to optimize after development.
Reserve space for media and third-party components before they load. Design asynchronous UI so loading does not unexpectedly displace existing content. Test pages under realistic network conditions and user flows, not only during initial load.
For production sites, combine field monitoring with DevTools debugging. Field data tells you whether real users experience instability; diagnostic tooling helps determine why.
FAQ
Is CLS part of Core Web Vitals?
Yes. CLS is the Core Web Vital that measures visual stability. The other current Core Web Vitals are LCP for loading performance and INP for responsiveness. (developers.google.com)
What is a good CLS?
A CLS of 0.10 or lower at the 75th percentile of page visits is considered good. (web.dev)
Is CLS measured in seconds?
No. CLS is a unitless score.
Can lazy loading increase CLS?
Lazy loading itself is not necessarily the problem. CLS occurs when lazy-loaded content appears without sufficient space having already been reserved.
Can CLS happen after page load?
Yes. Unexpected shifts can occur during scrolling, dynamic content updates, SPA transitions, or other post-load behavior. This is one reason field CLS may be higher than Lighthouse CLS. (web.dev)
Final Takeaway
CLS answers a simple question: does the page stay where the user expects it to stay?
A good CLS is not achieved by making every page static. Modern interfaces can still load content dynamically, animate elements, and react to user input. The important principle is predictability: reserve space before content arrives, avoid unexpectedly moving existing content, and validate the result using real-user data.
When a layout is stable by design, a good CLS score usually follows.
Sources
- web.dev — Cumulative Layout Shift (CLS). Last updated April 12, 2023. Cumulative Layout Shift (CLS) (web.dev)
- web.dev — Optimize Cumulative Layout Shift. Published May 5, 2020; updated February 7, 2025. Optimize Cumulative Layout Shift (web.dev)
- web.dev — Debug layout shifts. Published March 11, 2021; updated February 7, 2025. Debug layout shifts (web.dev)
- Google Search Central — Understanding Core Web Vitals and Google search results. Last updated December 10, 2025. Google Search Central Core Web Vitals documentation (developers.google.com)
- Chrome for Developers — Chrome UX Report: Metrics. Published June 23, 2022; updated September 15, 2026. Chrome UX Report Metrics (developer.chrome.com)
- Chrome for Developers — Performance features reference. Chrome DevTools Performance reference (developer.chrome.com)


