What is Cumulative Layout Shift (CLS) and how to fix it
The ultimate guide to finding and fixing the Cumulative Layout Shift for your site
Cumulative Layout Shift (CLS) - in short
Cumulative Layout Shift (CLS) is a user-centric metric that measures the visual stability of a web page. It essentially tracks how often and how much the content on a page moves around as it's loading. Layout shifts can be frustrating for users, as it 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!
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's 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 that will 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 easily 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 faction 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 = .50 * .25 = 0.125
Expected VS unexpected layout shifts
Not all layout shifts are bad, only the ones that you do not expect. When you clicks on a 'load more items' link for example you would expect more items to appear on the page and the 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 5 second duration. The session with the largest CLS score will become the final CLS score.
If, for example, during the first 5 seconds the CLS score is 0.095, then in the next 5 second sessions 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.
A quick reminder: 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 First Contentful Paint, the Largest Contentful Paint and the First Input Delay.
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 make 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's 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 though 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 Cumulatieve Layout Shift causes and how to fix them
The origin of all layout shifts is basically the same. At some time an element that was placed above another element took up more or less space the before. This is typically due to one or more of these causes:
- Images, iFrames or video's
- Ads
- Injected content
- Animations
- Slow interactions
- Web fonts
CLS caused by images, video's and iFrames
Layout shifts caused by images, video's 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.
<img src="img.jpg" width="200" height="200">
<style>
img{
max-width:100%;
height:auto
}
</style>
Note that dimensions can also be defined as a style property or even by setting the aspect-ratio style property.
CLS caused by webfonts
A cumulative lay out shift can be caused by webfonts. WebFonts are 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 then the final webfont.
There are a lot of methods to 'fix' the layout shift caused by web fonts. They are based on 2 techniques:
1. Make the fallback font match the webfont more closely. The most effective way is by overriding the @font-face descriptors
The second way is by speeding 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 preload your critical web fonts,
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
CLS issues caused by AJAX
AJAX allows web pages to be updated asynchronously by exchanging data with a web server behind the scenes. Obviously 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. Obviously 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% - 40% = 10% distance-fraction) is still a lot smaller thean 50% distance-fraction.
Here is an example on how to do this:
<style>
#ajax{height:400px}
#ajax.loaded{height:auto;}
</style>
<script>
Fix CLS issues caused by ads
Ads will often load (a lot) 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 just won't stay still'. To fix this also reserve the space for the ads, especially the ads in the visible viewport.
<style>
// rectangle mobile ad
.ad{min-height:250px;background:#dedede}
// banner desktop ad
@media only screen and (min-width: 600px) {
.ad{min-height:90px}
}
</style>
Need your site lightning fast?
Join 500+ sites that now load faster and excel in Core Web Vitals.
- Fast on 1 or 2 sprints.
- 17+ years experience & over 500 fast sites
- Get fast and stay fast!