Google’s Core Web Vitals initiative has taken the SEO and Web Performance worlds by storm and many sites are busy optimizing their Page Experience to maximize the ranking factor. The Cumulative Layout Shift metric is causing trouble to a lot of sites, so let’s have a look at ways of addressing any issues for that metric.
Cumulative Layout Shift (CLS) attempts to measure those jarring movements of the page as new content — be it images, advertisements, or whatever — comes into play later than the rest of the page. It calculates a score based on how much of the page is unexpectedly moving about, and how often. 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!
In this article, I’m going to discuss some front-end patterns to reduce CLS. I’m not going to talk too much about measuring CLS as I’ve covered that already in a previous article. Nor will I talk too much about the mechanics of how CLS is calculated: Google has some good documentation on that, and Jess Peck’s The Almost-Complete Guide to Cumulative Layout Shift is an awesome deep dive into that too. However, I will give a little background needed to understand some of the techniques.
CLS is, in my opinion, the most interesting of the Core Web Vitals, in part because it’s something we’ve never really measured or optimized for before. So, it often requires new techniques and ways of thinking to attempt to optimize it. It’s a very different beast to the other two Core Web Vitals.
Looking briefly at the other two Core Web Vitals, Largest Contentful Paint (LCP) does exactly as its name suggests and is more of a twist on previous loading metrics that measures how quickly the page loads. Yes, we’ve changed how we defined the user experience of the page load to look at the loading speed of the most relevant content, but it’s basically reusing the old techniques of ensuring that the content loads as quickly as possible. How to optimize your LCP should be a relatively well-understood problem for most web pages.
One reason that CLS is different is that it is measured through the lifetime of the page — that’s the “cumulative” part of the name! The other two Core Web Vitals stop after the main component is found on the page after load (for LCP), or for the first interaction (for FID). This means that our traditional lab-based tools, like Lighthouse, often don’t fully reflect the CLS as they calculate only the initial load CLS. In real life, a user will scroll down the page and may get more content dropping in causing more shifts.
CLS is also a bit of an artificial number that is calculated based on how much of the page is moving about and how often. While LCP and FID are measured in milliseconds, CLS is a unitless number output by a complex calculation. We want the page to be 0.1 or under to pass this Core Web Vital. Anything above 0.25 is seen as “poor”.
Shifts caused by user interaction are not counted. This is defined as within 500ms of a specific set of user interactions though pointer events and scroll are excluded. It is presumed that a user clicking on a button might expect content to appear, for example by expanding a collapsed section.
CLS is about measuring unexpected shifts. Scrolling should not cause content to move around if a page is built optimally, and similarly hovering over a product image to get a zoomed-in version for example should also not cause the other content to jump about. But there are of course exceptions and those sites need to consider how to react to this.
CLS is also continually evolving with tweaks and bug fixes. It has just had a bigger change announced that should give some respite to long-lived pages, like Single Page Apps (SPA) and infinite scrolling pages, which many felt were unfairly penalized in CLS. Rather than accumulating shifts over the whole page time to calculate the CLS score like has been done up until now, the score will be calculated based on the largest set of shifts within a specific timeboxed window.
This means tha if you have three chunks of CLS of 0.05, 0.06, and 0.04 then previously this would have been recorded as 0.15 (i.e. over the “good” limit of 0.1), whereas now will be scored as 0.06. It’s still cumulative in the sense that the score may be made up of separate shifts within that time frame (i.e. if that 0.06 CLS score was caused by three separate shifts of 0.02), but it’s just not cumulative over the total lifetime of the page anymore.
Saying that, if you solve the causes of that 0.06 shift, then your CLS will then be reported as the next largest one (0.05) so it still is looking at all the shifts over the lifetime of the page — it’s just choosing to report only the largest one as the CLS score.
The Cumulative Layout Shift metric is causing trouble to a lot of sites, so let’s have a look at ways of addressing any issues for that metric. Google’s Core Web Vitals initiative has taken the SEO and Web Performance worlds by storm and many sites are busy optimizing their Page Experience to maximize the ranking factor.