What is Cumulative Layout Shift (CLS) and how to fix it
The ultimate guide to finding, measuring, and fixing Cumulative Layout Shift for your site

Cumulative Layout Shift (CLS) in short
Cumulative Layout Shift (CLS) is a Core Web Vital that measures the visual stability of a web page. It quantifies how much visible content unexpectedly moves during the page lifecycle, using the formula: impact fraction multiplied by distance fraction. A good CLS score is below 0.1, while scores above 0.25 are considered poor. At least 75% of page visits must score "good" to pass.
Cumulative Layout Shift (CLS) is a user-centric metric that measures the visual stability of a web page. It tracks how often and how much the content on a page moves around as it loads. Layout shifts can be frustrating for users, as they can lead to accidental clicks, broken page formatting, and a generally confusing experience.
Since 2020 the Cumulative Layout Shift (CLS) is one of the three Core Web Vitals metrics. The CLS represents the visual stability part of the Core Web Vitals and determines how stable the main content of the webpage is during its entire life cycle.
In simple terms: a good CLS score will ensure a visibly stable experience!

What is Cumulative Layout Shift (CLS)?
Cumulative Layout Shift (CLS) represents the "visual stability" part of the Core Web Vitals. The Cumulative Layout Shift (CLS) measures the movements of the page as content renders or new content is shown on the page. It calculates a score based on how much of the page is unexpectedly moving about and how far it moves. These shifts of content are very annoying, making you lose your place in an article you've started reading or, worse still, making you click on the wrong button!
Table of Contents!
What is a good Cumulative Layout Shift (CLS) score?
A good CLS score is anything between 0 and 0.1. If your CLS score is between 0.1 and 0.25 it needs improvement. Any CLS score above 0.25 is considered poor. To pass the Core Web Vitals for the Cumulative Layout Shift, at least 75% of your visitors need to have a "good" CLS score.

Importance of CLS in web performance and user experience
Cumulative Layout Shift (CLS) is linked to both web performance and user experience because it directly impacts how stable and predictable a webpage feels while loading. Here is why it matters:
- UX, engagement and brand perception: Unexpected layout shifts disrupt user flow, making it harder to find information, click on buttons, and interact with the page as intended. This frustration can lead to poor experiences where users abandon the website altogether. A website's user experience reflects on the brand behind it. Frequent layout shifts can give the impression of a poorly designed or maintained website, disrupt user engagement, and lead to decreased interaction and potentially higher bounce rates.
- Accessibility: Layout shifts can be particularly disruptive for users with disabilities who rely on assistive technologies or screen readers. A stable layout ensures everyone can navigate and interact with the website effectively.
- SEO and Search Ranking: The Core Web Vitals are a small but significant ranking factor in Google. Google, along with other search engines, prioritizes websites that offer a good user experience. CLS is one of the Core Web Vitals metrics that Google considers when ranking websites. Optimizing for CLS can give your website a competitive edge in search results.
How is CLS measured?
The CLS of a page can be measured with the Layout Instability API. The following is a simple usage of this API:
new PerformanceObserver((entryList) => {
for (const entry of entryList.getEntries()) {
console.log('Layout shift:', entry);
}
}).observe({type: 'layout-shift', buffered: true}); Calculating the CLS
The CLS is calculated using a simple, yet elegant formula:
CLS = sum(impact-fraction * distance-fraction)
The impact fraction measures how much of the visible content of the page has shifted. The distance fraction measures how far the content has shifted. If, for example, 50% of the page (how much) has shifted 25% (how far) of the viewport of the page, the CLS score = 0.50 * 0.25 = 0.125.
Expected vs. unexpected layout shifts
Not all layout shifts are bad, only the ones that you do not expect. When you click on a "load more items" link, for example, you would expect more items to appear on the page and the content of the page to shift.
That is why only unexpected layout shifts will cause a CLS contribution. For example, if a user clicks a button and in response new content will be added to the page (for example a menu dropdown), the layout shift will be excluded from the CLS. To be precise: layout shifts that occur within 500 milliseconds of user input will be excluded from calculations.
Layout shift sessions
When CLS was first introduced some sites were unfairly punished with a bad CLS score. For example, a page that implements infinite scrolling would have gotten the impact of the newly added content added to the total CLS score for each new scroll. That is why the CLS is now calculated in sessions. Each session has a maximum 5 second duration and a 1 second gap between layout shifts. The session with the largest CLS score will become the final CLS score.
If, for example, during the first session the CLS score is 0.095, then in the next session the CLS is 0.15, and for the last session the CLS score is 0, the final CLS score will be the highest of the three: 0.15.

CLS and the Core Web Vitals
Cumulative Layout Shift (CLS) is an important, user-centric metric for measuring visual stability. The Cumulative Layout Shift (CLS) is part of the Core Web Vitals along with the Largest Contentful Paint (LCP) and Interaction to Next Paint (INP). Together, these three metrics measure loading performance, interactivity, and visual stability.
How to measure CLS issues
1. Use Lighthouse to find Cumulative Layout Shifts
The easiest method to find layout shifts is by using Lighthouse in your own Chrome browser. Simply run a Lighthouse audit by right clicking anywhere on the page. Then select inspect element, select the Lighthouse tab in the now opened console and run the audit.
The audit results will show the Cumulative Layout Shift (CLS) score. Scroll down to Diagnostics and expand the Cumulative Layout Shift information to see what nodes are causing the layout shift.
To be honest I never really use this method myself. The lack of details on the exact distance of the layout shift makes these results harder to interpret.


2. Use the CLS Visualizer to find Cumulative Layout Shifts
The CLS Visualizer is a Chrome extension written by me. With a single button click all the layout shifts on the page are visualized. This is the first solution I go to when trying to determine a layout shift on a page. It is easy and will give a great visual overview of the Cumulative Layout Shift.

3. Use the Chrome Performance tab to find CLS
By far the best way to debug a layout shift is through the Chrome Performance tab. To open the performance tab, navigate to any page in Chrome and use this shortcut combination:
- Press Ctrl+Shift+I (Open Dev Tools)
- Press Ctrl+Shift+E (Start profiling and reload page)
Now inspect the timeline frame by frame by hovering your mouse over the timeline on the top and look for layout shifts (layout shifts are also colored red in the Experience section of the Performance tab).
4. Use RUM tools like Core/Dash
RUM stands for Real User Monitoring and RUM data can provide valuable real-time insights into the Core Web Vitals. RUM tools like Core/Dash can break down the Cumulative Layout Shifts into segments like browser, element, navigation type, specific URL or page type. This will help identify and fix poor performing pages and offending elements.

Common Cumulative Layout Shift causes and how to fix them
The origin of all layout shifts is basically the same. At some point an element that was placed above another element took up more or less space than before. This is typically due to one or more of these causes:
- Images, iframes or videos without explicit dimensions
- Ads loading late into the viewport
- Dynamically injected content
- CSS animations using layout triggering properties
- Slow user interactions
- Web fonts with mismatched fallbacks
CLS caused by images, videos and iframes
Images, videos and iframes are the usual suspects when it comes to Cumulative Layout Shift, as these elements make up the majority of CLS issues. For a detailed guide on this specific cause, see how to fix layout shift caused by auto sizing images.

Layout shifts caused by images, videos or iframes are always caused by missing dimensions. Most commonly this is because the height and width of the element is not defined in the HTML. A common, good practice pattern is to set the intrinsic width of the image in the HTML and use styling to auto scale to contain the image to its parent container.
Set explicit width and height attributes
The simplest and most effective way to prevent CLS from images and iframes is to always include width and height attributes directly in the HTML. Modern browsers use these attributes to calculate the aspect ratio before the resource loads, reserving the correct amount of space.
<!-- Images: always include width and height -->
<img src="hero.jpg" alt="Hero image">
<!-- Iframes: same principle -->
<iframe src="https://example.com/embed"
title="Embedded content">
</iframe>
<!-- Videos: always include dimensions -->
<video controls>
<source src="video.mp4" type="video/mp4">
</video>
<style>
img, iframe, video {
max-width: 100%;
height: auto;
}
</style> Use the CSS aspect-ratio property
For responsive layouts or when exact pixel dimensions are not available, the aspect-ratio CSS property provides an alternative way to reserve space. This is especially useful for containers that hold dynamic content or embedded media.
<style>
/* Reserve space for a 16:9 video container */
.video-wrapper {
width: 100%;
background: #f0f0f0;
}
/* Reserve space for a square image */
.avatar {
width: 80px;
object-fit: cover;
}
/* Responsive iframe container */
.embed-container {
width: 100%;
}
.embed-container iframe {
width: 100%;
height: 100%;
}
</style> CLS caused by web fonts
A Cumulative Layout Shift can be caused by web fonts. Web fonts are fonts that are not installed on your local computer or phone but downloaded from the internet. While the web font is not yet downloaded, the page is usually rendered with a fallback font. The size of this fallback font may differ from the final font. In this example the fallback font is slightly smaller than the final web font. For more information, see how to ensure text remains visible during web font load.

There are several methods to fix the layout shift caused by web fonts. They are based on two techniques:
1. Make the fallback font match the web font more closely. The most effective way is by overriding the @font-face descriptors.
2. Speed up the web fonts. This will make them available to the browser before the browser starts rendering. A common way to do this is to self-host your web fonts and preload your critical web fonts.
Font fallback matching with metric overrides
The most effective technique to eliminate CLS from web fonts is to create a fallback font definition that closely matches the dimensions of your web font. Using the size-adjust, ascent-override, descent-override, and line-gap-override descriptors, you can make the fallback font occupy nearly identical space. Combined with font-display: swap, this ensures text is visible immediately with minimal layout shift when the web font loads.
<style>
/* Define a matched fallback font */
@font-face {
font-family: 'My Font Fallback';
src: local('Arial');
}
/* Use the web font with the matched fallback */
@font-face {
font-family: 'My Font';
src: url('/fonts/myfont.woff2') format('woff2');
}
body {
font-family: 'My Font', 'My Font Fallback', sans-serif;
}
</style>
<!-- Preload the critical web font for faster loading -->
<link rel="preload" href="/fonts/myfont.woff2"
as="font" type="font/woff2" crossorigin> Tools like the Fallback Font Generator can automatically calculate the correct override values for your specific font pairing. For Google Fonts specifically, self-hosting your fonts gives you full control over the font-face declarations and preloading strategy.
CLS caused by CSS animations
CSS animations and transitions can trigger unexpected layout shifts when they animate properties that affect the layout of surrounding elements. Properties like top, left, width, height, margin, and padding cause the browser to recalculate the layout of the entire page, which results in CLS. For a detailed walkthrough, see how to fix layout shift caused by CSS transitions.
The solution is to use composited CSS properties like transform and opacity for animations. These properties are handled by the GPU compositor and do not trigger layout recalculations, so they produce zero CLS.
<style>
/* BAD: Animating top/left causes layout shifts */
.slide-in-bad {
position: relative;
animation: slide-bad 0.3s ease-out;
}
@keyframes slide-bad {
from { }
to { }
}
/* GOOD: Animating transform does NOT cause layout shifts */
.slide-in-good {
animation: slide-good 0.3s ease-out;
}
@keyframes slide-good {
from { }
to { }
}
</style> According to the HTTP Archive Web Almanac, 39% of mobile pages and 42% of desktop pages have non-composited animations contributing to CLS. Always check your animations to ensure they only use transform and opacity rather than layout-triggering properties.
Use CSS containment to isolate layout shifts
The CSS contain property tells the browser that an element's contents are independent from the rest of the page. This limits the scope of layout recalculations and can prevent layout shifts from propagating to surrounding elements.
<style>
/* Isolate ad containers from the rest of the page */
.ad-slot {
min-height: 250px;
}
/* For off-screen content, use content-visibility */
.below-fold-section {
}
</style> The contain: layout declaration ensures that any size changes within the element will not trigger layout recalculations for elements outside it. The content-visibility: auto property goes further by allowing the browser to skip rendering of off-screen content entirely, with contain-intrinsic-size providing an estimated size to prevent layout shifts when the content scrolls into view.
CLS issues caused by slow user interactions
In the example below the load more button clearly triggers a layout shift. However the layout shift will not be added to the CLS metrics. This is because this layout shift is intentional.
A browser will know this because the now visible elements have an attribute called "hadRecentInput". When this is set to true AND the layout shift happens within 500 ms of the input event (the button click) the layout shift will not be reported by the browser.

Ensure user interactions complete within 500ms. If an interaction takes longer than that, any resulting layout shift will count toward the CLS score. This is particularly relevant for AJAX requests that inject new content. For tips on optimizing interactive elements, see how to build a chat widget with perfect Core Web Vitals.
CLS issues caused by AJAX and dynamically injected content
AJAX allows web pages to be updated asynchronously by exchanging data with a web server behind the scenes. Injecting new content into any webpage could lead to a massive layout shift. That is why it is wise to reserve the space that is used for the new content. You do not know the height of the new content in advance, but what you can do is take an educated guess.
For example, if the average AJAX content takes up 50% of the screen, it is wise to reserve that 50%. When the new content ends up taking up 40 or 60% of the screen, the CLS (50% minus 40% = 10% distance fraction) is still a lot smaller than a 50% distance fraction.
Here is an example on how to do this:
<style>
#ajax { height: 400px; }
#ajax.loaded { height: auto; }
</style>
<script>
fetch('/ajax-content')
.then(response => response.json())
.then(result => {
let el = document.getElementById('ajax');
el.innerHTML = result.html;
el.classList.add('loaded');
})
</script> Post-load CLS: dynamic content and late-loading elements
Layout shifts do not only happen during the initial page load. Post-load CLS is caused by content that appears or changes size after the page has already rendered. Common culprits include:
- Late-loading advertisements: Ad networks often inject content seconds after the page has loaded. If the ad slot has no reserved space, the ad pushes all surrounding content down.
- Cookie consent banners: Banners that push page content down instead of overlaying it cause significant CLS. Use an overlay pattern (position: fixed) or reserve space at the top of the page.
- Lazy-loaded content above the fold: Content loaded via Intersection Observer that was initially hidden but appears in the viewport without reserved space.
- A/B testing scripts: Testing tools that modify the DOM after initial render can cause unexpected shifts. Run A/B test modifications server-side or within the initial HTML when possible.
- Infinite scroll implementations: New content appended at the bottom of a list can cause shifts if it changes the layout of existing elements. Ensure new content is only appended below the current scroll position.
The session window model (described above) means that even post-load shifts count toward CLS if they happen to fall within the worst session. Monitor your CLS attribution data in Core/Dash to identify which elements shift after load.
Fix CLS issues caused by ads
Ads will often load significantly later on the page. This makes Cumulative Layout Shifts caused by ads especially annoying. When multiple ads are loading in the visible viewport, the page simply will not stay still. To fix this, reserve the space for the ads, especially the ads in the visible viewport.
<style>
/* Reserve space for rectangle mobile ad */
.ad {
min-height: 250px;
background: #dedede;
}
/* Reserve space for banner desktop ad */
@media only screen and (min-width: 600px) {
.ad { min-height: 90px; }
}
</style> Case study: Rakuten 24 and the business impact of CLS
Rakuten 24, a major Japanese e-commerce platform, conducted a detailed study on the impact of Cumulative Layout Shift on their business metrics. By reducing CLS across their product and category pages, Rakuten 24 achieved remarkable results:
- 53.37% increase in revenue per visitor for users who experienced low CLS compared to those with high CLS.
- 33.13% increase in conversion rate for the same improved CLS cohort.
- 15.20% decrease in bounce rate among visitors with stable page experiences.
These numbers demonstrate that CLS is not merely a technical metric. Visual instability directly costs businesses revenue by frustrating users during their browsing and purchase journey. When elements shift unexpectedly, users lose trust, misclick, and abandon their sessions. The Rakuten 24 study confirms that investing in CLS optimization has a measurable return on investment, particularly for e-commerce sites where every interaction counts.
What real-world CLS data shows
CoreDash data shows CLS is the best-performing Core Web Vital, with 92.8% of page loads on corewebvitals.io achieving a "good" score and virtually no device gap between mobile and desktop. Both desktop (92.8% good) and mobile (92.7% good) achieve near-perfect CLS scores, with a p75 of 0 on both device types.
This stands in contrast to metrics like LCP and INP, where mobile performance is significantly worse than desktop. CLS is uniquely better on mobile than desktop across the broader web, which is the reverse of every other Core Web Vital.
Globally, according to the HTTP Archive Web Almanac 2024, the picture is less optimistic:
- 72% of websites achieve good CLS scores overall, while 11% have poor CLS.
- 66% of mobile pages have at least one unsized image (down from 72% in 2022, but still a major CLS contributor).
- 39% of mobile pages have non-composited animations contributing to CLS.
- Only 11% of pages preload web fonts, meaning the vast majority of sites are vulnerable to font-swap layout shifts.
CLS has shown steady year-over-year improvement globally, but the data reveals that unsized images and non-composited animations remain the two most common causes. Addressing these two issues alone would eliminate layout shifts for a large portion of the web.
Frequently asked questions about CLS
What is a good CLS score?
A good CLS score is 0.1 or lower. Scores between 0.1 and 0.25 need improvement, and scores above 0.25 are considered poor. To pass the Core Web Vitals assessment, at least 75% of your page visits must have a CLS score of 0.1 or better. Unlike time-based metrics such as LCP or INP, CLS is a unitless score calculated from the impact fraction and distance fraction of layout shifts.
What causes Cumulative Layout Shift?
The most common causes of CLS are images and iframes without explicit width and height attributes, web fonts that swap in with different dimensions, dynamically injected content (ads, cookie banners, promotional bars), CSS animations that use layout-triggering properties (top, left, width, height instead of transform), and late-loading third-party scripts. According to global data, 66% of mobile pages have unsized images and 39% have non-composited animations, making these the two leading CLS contributors.
Do user-initiated layout shifts count toward CLS?
No, layout shifts that occur within 500 milliseconds of a user interaction (click, tap, or keypress) are excluded from the CLS score. The browser marks these shifts with a "hadRecentInput" flag and does not include them in the calculation. However, if the response to a user interaction takes longer than 500 milliseconds, any layout shift that occurs after that 500ms window will count toward CLS. This is why it is important to ensure all interactive responses complete quickly.
How is CLS calculated?
CLS is calculated using the formula: impact fraction multiplied by distance fraction. The impact fraction is the percentage of the viewport that was affected by the shift. The distance fraction is how far the elements moved, as a percentage of the viewport. For example, if 50% of the viewport shifted and the content moved 25% of the viewport height, the CLS score for that shift would be 0.50 * 0.25 = 0.125. The browser groups shifts into "session windows" (maximum 5 seconds, with a 1 second gap between shifts), and the largest session window becomes the final CLS score.
Does CLS affect SEO rankings?
Yes, CLS is one of the three Core Web Vitals that Google uses as a ranking signal. While Google has stated that the Core Web Vitals are a relatively small ranking factor compared to content relevance, they can be a tiebreaker between pages with similar content quality. More importantly, poor CLS directly impacts user behavior: the Rakuten 24 case study showed a 53.37% difference in revenue per visitor between users who experienced low CLS versus high CLS. Improving CLS benefits both your search rankings and your conversion rates.
Related guides and deep dives
Explore these detailed guides for specific CLS optimization techniques:
- Fix layout shift caused by CSS transitions: Learn how to identify and replace layout-triggering CSS animations with composited alternatives.
- Fix layout shift caused by auto sizing images: A complete walkthrough for adding proper dimensions to images and responsive containers.
- Self-host Google Fonts: Reduce font-loading CLS by self-hosting fonts with proper font-display and preloading strategies.
- Ensure text remains visible during web font load: Configure font-display and font metric overrides to eliminate font-swap layout shifts.
- Build a chat widget with perfect Core Web Vitals: A case study on implementing third-party widgets without introducing CLS, INP, or LCP regressions.
For a complete overview of all Core Web Vitals metrics and optimization strategies, visit the Core Web Vitals overview or use the Ultimate Core Web Vitals Checklist to audit your site.
Urgent Fix Required?
Google Search Console failing? I offer rapid-response auditing to identify the failure point within 48 hours.
- 48hr Turnaround
- Rapid Response
- Failure Identification

