Cumulative Layout Shift (CLS) measures the visual stability of a page as it loads. It does this by looking at the size of the items and how far they move. It is one of the three Core Web Vitals metrics that Google uses to measure page experience.
The CLS is calculated during the five-second window where the most lag occurs.
Expected layout changes, such as after a user action, are correct and expected. Offsets within 500ms of user interaction are excluded from calculations.
Here’s how it’s measured:
layout change score = impact fraction x distance fraction
Or said in a more understandable way, it is:
layout shift score = % of viewport that changed * distance moved by unstable element
The reason CLS is important is that it’s annoying when you try to click something on a moving page and end up clicking something you don’t intend to.
It happens to me all the time. I click on a thing and all of a sudden I click on an ad and I’m not even on the same website anymore. As a user, I find this frustrating.
Common causes of SLC include:
- Images without dimensions.
- Ads, embeds, and iframes without dimensions.
- Applying fonts or styles late in loading.
Let’s see what your CLS score should be and how to improve it.
A good CLS score is less than or equal to 0.1 and should be based on data from the Chrome User Experience Report (CrUX). This is data from real Chrome users who are on your site and have agreed to share this information. You need 75% of page loads to have a CLS score of 0.1 or less.
Your page can be categorized into one of the following buckets:
- Good: <=0.1
- To be improved: >0.1 and <=0.25
- Bad: >0.25
72.8% of sites have good CLS scores in April 2023. This is an average across the entire site. As mentioned, you need 75% of page loads to have a CLS score of 0.1 or less to be classified as good.
CLS is the most improved Core Web Vital since Google’s push for faster websites.
When we conducted a page-level study using Site Audit data, we have seen that CLS is similar on desktop and mobile.
We also noted that many sites struggle with CLS, especially on slower connections.
CLS is worse in page-level data than in original data. It’s likely that people will improve their main pages, which drive more traffic, while leaving many other pages with failing scores.
There are different ways to measure CLS: field data and laboratory data.
The field data comes from the Chrome User Experience Report (CrUX), which is data from actual Chrome users who choose to share their data. This gives you the best idea of real-world CLS performance. This is also what you will actually be measured on by Google for Core Web Vitals.
Laboratory data is based on testing with the same conditions to make testing reproducible. Google does not use it for Core Web Vitals. But it’s useful for testing because the CrUX/terrain data is a 28-day rolling average, so it takes a while to see the impact of changes.
The best tool to measure CLS depends on the type of data you want (lab/field) and whether you want it for one or multiple URLs.
Measure CLS for a single URL
Page speed information extracts page-level field data that you cannot otherwise query in the CrUX dataset. It also runs Google-based lab tests for you Headlight and gives you original data so you can compare page performance to the whole site.
Measure CLS for many URLs or an entire site
You can get CrUX data in Google Search Console which is categorized into good, needs improvement and bad.
Clicking on any of the issues gives you a breakdown of the affected page groups. Groups are pages with similar values that likely use the same template. You make the changes once in the template, and it will be fixed on all pages in the group.
If you want both lab data and large-scale field data, the only way to achieve that is to use the PageSpeed Insights API. You can connect to it easily with Ahrefs Site Audit and get reports detailing your performance. This is free for verified sites with a Ahrefs Webmaster Tools (AWT).
Note that the Core Web Vitals data displayed will be determined by the user agent you select for your scan during setup. If you are exploring from mobile, you will get mobile CWV values from the API.
In Page speed information, if you select CLS in the “Diagnostics” section, you can see all related issues such as “Avoid large layout changes”. These are the problems you will want to solve.
In most cases, to optimize CLS, you will work on issues related to images, fonts, or possibly injected content. Let’s examine each case.
1. Reserve space for images, videos, iframes
For images, what you need to do is reserve the space so that there is no lag and the image just fills that space. This may mean setting the height and width of the images by specifying them in the tag like this :
<img src=“cat.jpg" width="640" height="360" alt=“cat with string" />
For responsive images, you should use an srcset like this:
srcset="https://ahrefs.com/puppy-1000.jpg 1000w, https://ahrefs.com/puppy-2000.jpg 2000w, https://ahrefs.com/puppy-3000.jpg 3000w"
alt="Puppy with balloons" />
You’ll also want to reserve space for things like videos and iframes. For dynamic content like ads, you’ll want to reserve the maximum amount of space needed.
There’s also a relatively new CSS property called aspect ratio that will let you set a dynamic width based on screen size, and the browser will calculate the appropriate height for you.
2. Optimize fonts
For fonts, the goal is to get the font to the screen as quickly as possible and not swap it with another font. When a font is loaded or changed, you end up with a noticeable change like a flash of invisible text (FOIT) or a flash of unstyled text (FOUT).
If you can use a system font, do so. There is nothing to load, so there are no delays or changes that will cause lag.
If you need to use a custom font, the current best method to minimize CLS is to combine (which will try to grab your font as soon as possible) and font-display: optional (which will give your font a small window of time to load).
If the font does not arrive in time, the initial page load will simply display a default font. Your custom font will then be cached and will appear on subsequent page loads.
3. Use Animations That Don’t Trigger Layout Changes
Some CSS property values trigger layout changes, such as “box-shadow”, “box-sizing”, “top”, “left”, etc. which should not be animated. Instead, you’ll want to use “transform” animations to avoid layout changes.
4. Make sure your pages are eligible for bfcache
The back/forward cache keeps pages in the browser’s cache. It allows instant loading of an already loaded page, which means that no layout changes will occur.
There is a decent amount to this optimization. The main strategies are listed below and you can read more about them. here.
- Never use unload event
- Minimize the use of Cache-Control: no-store
- Update stale or sensitive data after restoring bfcache
- Avoid window.opener references
- Always close open connections before the user leaves
- Test to make sure your pages can be cached
Since the introduction of CLS, we have already seen innovations such as bfcache and the CSS image format that help solve the problem. I expect we’ll see more innovation and more new ways to prevent layout changes in the future.
If you have any questions send me a message on Twitter.