How to Improve CLS - Cumulative Layout Shift
One of the most annoying things we encounter while surfing a website is a sudden change on the page. It could be an ad appearing out of nowhere, the content you are reading suddenly moves position, or a link moving down the page right when you are about to click. Guess what? Google hates it too and created Cumulative Layout Shift (CLS), a metric to measure how often such layout shifts happen for real users.
Cumulative Layout Shift is a part of Core Web Vitals, and it measures the stability (or lack thereof) of contents. While it is a new metric, the issues CLS measures have been plaguing the Web for as long as I can remember.
In essence, it is a user-centric metric that you have to start optimizing to improve CLS score as it, along with other Core Web Vitals like First Contentful Paint (FCP), First Input Delay (FID) and Largest Contentful Paint (LCP) will have a direct impact on your search engine rankings.
Expected Shifts vs. Unexpected Shifts
Let’s face it. Not all shifts are equal.
Generally speaking, if the layout shift happens because of something a user-initiated, then it can be considered an expected shift (or a good shift). For example, you click on the mobile menu to open the navigation menu, and it slides in from the right side. Another good example is when you click on a link or a button, and a loading bar slides in at the top of the page, pushing the content down the screen a tad.
Google understands this very well. So any shift that happens within 0.5s second (500ms) of the last user interaction will not be counted in your Cumulative Layout Shift score. In our above example, both the off-canvas navigation menu and loading bar have 0.5 seconds to display from the moment a user interacts with the page.
Unexpected shifts, on the other hand, are a different story.
(Example of Bad Layout Shift. Source: Web.Dev)
The above video illustrates perfectly well what a bad layout shift is. I am sure many of you have faced this and similar scenarios on a daily basis that irks you to no end. Google hates those too as it really detracts from a good user experience.
What is a Good CLS Score?
The general guideline by Google is that any CLS scores under 0.1 are good, and any above 0.25 are bad.
Unlike other Core Web Vital metrics, CLS is not calculated as a time measure. The formula of layout shift score is:
Layout Shift Score = Impact Fraction * Distance Fraction
These measure the movement of unstable elements in relation to the viewport size. Then CLS is the cumulative score of all layout shift score.
Also, keep in mind that since mobile phones have a smaller screen real estate, layout shifts on mobile are a lot more impactful. When you test for your Cumulative Layout Shift score, you will get a separate CLS score for mobile and desktop. It is reasonable to expect that you will have to optimize for both desktop and mobile since Google is pushing a mobile-first agenda.
How to Check for Layout Shifts
CLS can be measured both in the field or in the lab using a few available tools.
Google PageSpeed Insights and Search Console (Core Web Vitals Report) are the two most commonly used tools for field testing the Cumulative Layout Shifts score. You may also use Chrome Lighthouse and Chrome DevTools as lab tools.
One thing to note though is that while knowing the CLS score can be done by checking your website using PageSpeed Insights, to really check your layout shifts is not an easy task. Typically this is because when you are testing on a development machine (usually your own computer), all website caches are already on your browser, along with all relevant assets (CSS, fonts, images, etc). This will make any layout shift happen so quickly that it is very hard to detect with the naked eyes. It is also possible that you may notice some layout shifts happen but find it hard to identify all the changes.
Here is one very useful method I recommend: intentionally slowing down the loading speed of your website when you test.
Don’t fret. I am not recommending loading heavy resources. Instead, we are going to do this using Chrome DevTools.
Open up Chrome Development Tools (by clicking F12) on the page you want to check for layout shifts and go to the Network tab. Then click on the dropdown box labeled “Online.” This is where you can artificially lower down your connection speed to test your site on slow connections.
Instead of using presets here, let’s add a significantly slower speed than your connection. Something like 150kbps. With this unrealistically slow speed, your site will load in such slow motion that you can now see everything including which elements resize and how much layout shifts they are causing. Any dynamic elements will also load slowly, and any layout shifts will be visible.
After you added a much slower connection speed, go to the Elements tab and go to “More Tools” (within the menu of three dots) and select “Rendering.” At the bottom, you will see “Layout Shift Regions.” Enable it and then reload the page. Now you can see that areas with layout shifts will be highlighted in the blue color.
You can also see the specific element causing the CLS in the report of PageSpeed Insights tool.
Another very easy way is by going to the Performance tab in Chrome Developer Tools. Then click on “Start Profiling and Reload Page.” It will refresh the page and give you a profiler report, which includes a section named “Experience.” In it, you can select “Layout Shift.” The HTML element that causes the layout shift will be highlighted. If you want to see a summary of the shift, as well as the original and new locations of the object shifting, you can click on the “Layout Shift.”
How to Improve CLS Score
Now that you know how to check for CLS score and layout shifts, let’s take a look at some of the most common issues that are detrimental to your CLS score. In each, I will also show you ways to optimize or resolve the issues.
Speed Loading Fonts
Not so surprisingly, fonts are among the top reasons for page speed performance issues including CLS score.
Almost all websites today use at least one custom web font (from Google Fonts or other sources), if not more. And since those fonts have different individual letter sizes and spacing from the default browser fonts, when the custom font finally loads, it does cause layout shifts throughout the website. This is especially obvious if the font you are using is slow to load for any number of reasons.
While it is entirely possible to minimize this, you may never be able to completely eliminate this issue. The main reason being that the custom web fonts are necessary for both branding and good design. After all, you probably don’t want to keep using the default browser fonts.
My first suggestion is to preload your fonts (rel=preload) so that the font assets have a higher priority in page rendering. I also suggest that you locally host the fonts unless you have a slow hosting because then this is the least of your problem. I also recommend to use aggressive caching, as well as to use a good CDN to host static assets such as your fonts. This way, the CDN can serve your visitors from the closest and fastest network, resulting in higher loading speed and thus minimizing the layout shifts caused by fonts.
One thing to keep in mind, though, is that preloading your fonts may have a negative impact on your Largest Contentful Paint (LCP) metric, as I explained in my article on How to Improve LCP – Largest Contentful Paint.
Embeds and iFrames
Embeds allow you to embed and display web content from elsewhere on your page — for example, YouTube videos, Google Maps, Instagram posts, and so on. The methods of embed can vary, including:
- Inline HTML code
One issue, however, is that most of the embeddable widgets don’t include the accurate dimension of the embedded content in advance. For instance, if you were embedding a Twitter post, it could be a text-only post or may contain an image. As a result, most platforms that offer embeddable widgets don’t include the dimensions in their code. So when the embedded content finally loads, it can cause significant layout shifts.
(Example of Bad Shift on Embeds & iFrames. Source: Web.Dev)
A good way to optimize your CLS score if you are using embeds is to predetermine the necessary dimensions and use a placeholder or fallback. You can do this simply by loading your final embed, and inspect it using Chrome Developer Tools to get the height of the embed. This way, you can then style your placeholder with the right height so that it will reserve enough space and not cause layout shifts. Some platforms like Google Maps will let you define the width and height of the map embed so it is not an issue.
(Example of Embeds & iFrames with Predefined Dimensions. Source: Web.Dev)
Dimensionless Images and SVGs
Images are yet another very common culprit for causing unexpected layout shifts, specifically dimensionless images.
What does “dimensionless” mean? These are images that have no specification of the width and height. What happens is that when you visit a webpage with such dimensionless images, the browser won’t reserve any space for those images. And once the images load (usually after textual contents have loaded since images have a larger file size than HTML and CSS), they will cause bad layout shifts by pushing the contents from original positions.
(Example of Bad Shift Caused by Dimensionless Image. Source: Web.Dev)
One way to avoid this is by, obviously, specifying the width and height of your images. But this won’t do well in a responsive design, so another way is to use the aspect ratio in CSS. By using the aspect ratio, you need to specify a single dimension (height or width) so you won’t run into problems with responsiveness.
(Example of Image with Predefined Dimension. Source: Web.Dev)
For SVGs, they will size down according to the dimensions of the container HTML element. However, before this sizing down happens, SVGs tend to load in their full sizes which cause CLS. The way to solve it is to define the desired width and height in the code of SVG itself. This way, the SVGs will load in the exact dimensions you want and will not cause any unexpected layout shifts.
‹svg xmlns="http://www.w3.org/2000/svg" width="40px" height="40px" viewBox="...I got the "good" SVG. (Click to open in a new window)
There are many other specific ways, but the aforementioned suggestions are good starting points. This way, the browser will reserve space for your images to load and won’t cause layout shifts.
Ads are, in fact, one of the biggest perpetrators behind layout shifts. For starters, most ad networks often use dynamic ad sizes instead of fixed dimensions. This is due to increasing ad performance, click-through rates, and such depending on ad sizes. And since ad contents are hosted on different servers, loading them is undoubtedly slower than the rest of your webpage.
(Example of Ads Causing Bad Shift. Source: Web.Dev)
There are a few best practices you can use to reduce, if not eliminate, the bad layout shift caused by ads. One of them is to pre-allocate space for the ad. You can do so by using CSS to style the element for the dynamic ad contents load. One piece of advice is to reserve the largest possible size, but this may leave blank space around the area if smaller ads load. So this is one thing to keep in mind when you design your page layouts.
One caution, however, is to be aware is what happens when there is no ad returned from the ad network even when you have reserved a space. My suggestion is to show a placeholder as the reserved space may collapse if there is no content loaded.
(Example of Ad with Predefined Dimension. Source: Wev.Dev)
Ultimately, there is no one-size-fit-all solution when it comes to ads. In most cases, it will depend on your ad network and historical data of ads served to determine the best possible route for you to reserve space for ad contents.
Every website has dynamic content. We have all seen the various types — related contents, newsletter signup forms, and even sticky bars with some sort of message or notifications on them.
(Example of Bad Shift Caused by Related Contents. Source: Web.Dev)
Fortunately, the simplest way to avoid layout shifts caused by dynamic content is to insert dynamic content below existing content, not above. However, the exception is when you must display a dynamic content above due to user interaction.
If there is no way you can avoid inserting dynamic content above existing content, you can simply reserve enough space for it.
Remember that in an earlier section I mentioned what Google defines as Good Layout Shifts (Expected Layout Shifts)? Any layout shift in response to a user interaction are good shifts. However, your site must load whatever it needs to load within 0.5 second (500ms) of the last user interaction to not count any layout shift occurs towards your Cumulative Layout Shift score. So essentially, optimizing your website for other speed and responsiveness metrics is really important for your CLS score.
The recommendation from Google for an optimal CLS score is to use the transform(scale) property in CSS to avoid causing unexpected layout shifts. Primarily this is because transform CSS property does not trigger any geometry changes, unlike other animation-related CSS properties.
If you were to use Lottie animations, any elements sliding in from left-right edges, or using fade in/out effects, I recommend you still define element’s height property so that it will not cause a bad and unexpected layout shift.
I understand that optimizing the CLS score is a lengthy and very involved process. While it may not have a significant impact on search engine ranking right now as opposed to other Core Web Vitals metric, as Google gathers more field data related to CLS score, it will become an important metric.
Also, by eliminating or significantly reducing the layout shifts, you will improve the user experience of your website which in turn can lead to an increase in conversions and clickthrough rates. No matter how you look at it, optimizing CLS score is a win.
Page Speed Optimization Course
FREE page speed recommendations for YOUR site
Send me your site URL, and I will personally check your site and give you a few recommendations for free.