The Cumulative Layout Shift (CLS) metric measures how much unexpected layout shifts affect the user experience on a page. These layout shifts occur when content moves around without prior user input.
In this article, you'll learn how to solve the most common CLS problems.
Reducing your CLS will benefit your website’s UX and SEO, especially now that the Core Web Vitals are part of Google's ranking algorithm.
Here’s a quick overview of everything covered here:
Let’s get started.
1. Images and videos with no dimensions (width and height attributes)
2. Ads, embeds and iFrames without reserved space
3. Web fonts causing flashes of unstyled or invisible text - FOUT and FOIT
While this metric was changed to be more neutral to the time on page, these elements remain a constant source of CLS issues.
Other elements can also cause layout shifts, so you should learn how to analyze and debug CLS issues. If you’re interested, just skip ahead to the “Measuring and Debugging CLS Problems” section.
Before diving into specific solutions, we have to discuss the two most important principles for avoiding layout shifts.
This is the easiest and most common way to ruin your CLS score. Here’s what happens when an ad is placed at the top of a page:
Source - creativebloq.com
The ad caused everything on the page to move, i.e., there was a massive unexpected layout shift. That’s the whole problem with inserting content at the top.
Many elements can cause this issue, including:
Now, if you’re in a situation where you absolutely have to place new content at the top of the viewport, there are ways to mitigate the damage.
Which brings us to the second principle.
That’s why width and height attributes are your best friends when it comes to avoiding CLS issues.
Using these attributes in the HTML markup helps the browser allocate enough space for the content in advance. This reduces layout shifts when that content appears on the page.
Or in other words:
When you have to break the first principle (don’t insert content over existing content), apply the second principle (reserve enough space in advance) to avoid CLS issues.
Now let’s move on to the specific tips.
As I already said, these attributes let the browsers know how much space they must allocate for each image or video.
This is probably the easiest way to fix current CLS issues and prevent potential ones. It’s as simple as adding a few lines to the HTML markup:
At NitroPack, we call this Preemptive Image Sizing and we do it without adding width and height attributes. Regardless of the method, the important thing is to alert the browser so it can reserve space in advance.
Some websites also use placeholders and skeleton UIs for even better image loading.
For example, developers can place low-quality placeholder images with a similar background to the final image.
Techniques like these don’t prevent CLS problems alone (you still need width and height attributes!), but they’re great for improving perceived performance.
In the video below, Addy Osmani talks about optimizing CLS for an eCommerce store that uses placeholders for their product images:
Their approach is a bit more advanced, but it’s still worth considering, especially if you have lots of products on your site.
Let’s go back to our example of an ad causing massive layout shifts:
Source - forbes.com
This is a common problem, especially for news websites, as their business model relies on ad revenue.
Ads can cause layout shifts during different points of their lifecycle since they're usually loaded asynchronously. I recommended checking out Google’s documentation for more details on this issue if you’re working with their Publisher Tags.
In general, the solution with ads is to statically reserve space for them in advance. Doing this ensures the ad container is styled correctly before the ad library loads.
You can look at historical data to determine how large the reserved spaces should be for each ad.
Here’s an example of how ads with enough reserved space load:
Source - yahoo.com
As you can see, ads on Yahoo's site (at least above the fold) don’t move the content below or around them.
Now, in some cases, the ad network might not deliver an ad to the container. If that happens, don’t collapse the container, as that will cause a layout shift. Use a placeholder instead.
Also, if your website receives an ad larger than the reserved slot, use the overflow: hidden property. It's a great failsafe for avoiding CLS problems that might be hard to detect otherwise.
Use width and height in the HTML markup to reserve space for ads in advance;
Don’t collapse the container if the ad network doesn’t serve an ad;
Use overflow: hidden to prevent larger ads from overflowing the container.
This is part of the approach that Yahoo takes to avoid layout shifts:
For embeds, you should also use a placeholder or fallback.
Just make sure to analyze the final element with DevTools to know how much space it takes up.
Techniques like reserving space and using placeholders/fallback are also necessary when injecting dynamic content. Apply them whenever you need to insert elements without prior user input.
Unoptimized web font delivery can cause huge layout shifts.
For example, when a fallback font is switched with the downloaded web font, we have a “flash of unstyled text” or FOUT.
In other cases, “invisible” text is displayed before the web font is ready. That’s called a “flash of invisible text” or FOIT.
Before diving into the specifics, it’s worth noting that there’s no perfect strategy for dealing with web fonts.
As of today, using font-display: optional in combination with link rel: “preload” for your most important fonts is generally regarded as the best overall strategy.
The reason why it works is a long topic, but the TL;DR is this:
The optional value won’t cause a re-layout when the web font is ready. At the same time, the preloaded font will likely meet the first paint, ensuring no layout shifts occur.
To preload a font, you have to add a few attributes to the head tag of the page, like this:
Adding the like as=”font”, type=”font/woff2” and crossorigin helps the browser prioritize resources when rendering the page.
Again, if you want an in-depth explanation of how and why this method works, check out:
Web.dev's demo for preloading web fonts;
Simon Hearn’s fantastic guide on avoiding layout shifts caused by web fonts.
Or you can check our article where we take a look at 7 font loading techniques to improve your Core Web Vitals.
In some cases, it might not be obvious what causes a layout shift.
Fortunately, there are a few tools you can use to analyze any CLS problem.
Open a page you want to analyze, right-click and select “Inspect”.
Next, click on “More Options” and go to “Rendering”.
After that, select the “Layout Shift Regions” options and reload the page.
As the page loads, all of the shifting elements will be highlighted in blue:
Source - forbes.com
You can also use the “Performance” panel and hover over the “Layout Shift” area in the “Experience Section”.
Keep in mind that DevTools won’t tell you if a shift is “good” or “bad”. Don’t be alarmed if something moves around after you click on a button or scroll down the page - that doesn’t contribute to CLS, as the layout shift is initiated by a user.
The Lighthouse audit shows you which elements contribute the most to your CLS score.
Again, click “Inspect” on the page, but this time go to “Lighthouse”.
Click on “Generate report” and wait for Lighthouse to work its magic.
Once it's ready, go to the “Diagnostic” section and look for the “Avoid large layout shifts” warning. When you click on it, it will show you which elements contribute the most to layout shifts.
Lastly, a personal favorite of mine is this Layout Shift GIF generator.
It’s really easy to use as it only requires a URL and it provides a GIF with all of the layout shifts on the page. The results look like this:
You can also use it to check a mobile (Nexus 5X) version of the page.
On top of that, you can use a command line version of the tool by installing it directly from NPM. Check out the GitHub page for more information.
After fixing your CLS score, it’s a good idea to periodically look at field data to detect potential problems.
Field data are gathered by the Chrome User Experience Report (CrUX). These data show how real users experience your site.
You can find field data directly below your overall score in PageSpeed Insights:
If PageSpeed Insights doesn’t display this field due to lack of data, you can use different tools to access the CrUX dataset:
BigQuery - requires a Google Cloud project and SQL skills;
The Core Web Vitals report in Google Search Console - very beginner-friendly, useful for marketers, SEOs and webmasters.
Which tool you choose depends on your preference. The important thing is to be aware of any CLS issues that your visitors might be having.
And since Google uses the previous 28-day period to determine whether your site passes the Core Web Vitals audit, you should check the field data at least once a month.
Finally, always look for unexpected layout shifts after code updates to your site. These shifts can sneak in during development and remain unnoticed for a long time.
Evgeni writes about site speed and makes sure everything we publish is awesome.