Cumulative Layout Shift (CLS) is a Google Core Web Vitals metric that measures a user experience event.
CLS became a ranking factor in 2021 and that means it’s important to understand what it is and how to optimize for it.
What Is Cumulative Layout Shift?
CLS is the unexpected shifting of webpage elements on a page while a user is scrolling or interacting on the page
The kinds of elements that tend to cause shift are fonts, images, videos, contact forms, buttons, and other kinds of content.
Minimizing CLS is important because pages that shift around can cause a poor user experience.
A poor CLS score (below > 0.1 ) is indicative of coding issues that can be solved.
What Causes CLS Issues?
There are four reasons why Cumulative Layout Shift happens:
- Images without dimensions.
- Ads, embeds, and iframes without dimensions.
- Dynamically injected content.
- Web Fonts causing FOIT/FOUT.
- CSS or JavaScript animations.
Images and videos must have the height and width dimensions declared in the HTML. For responsive images, make sure that the different image sizes for the different viewports use the same aspect ratio.
Let’s dive into each of these factors to understand how they contribute to CLS.
Images Without Dimensions
Browsers cannot determine the image’s dimensions until they download them. As a result, upon encountering an<img>
HTML tag, the browser can’t allocate space for the image. The example video below illustrates that.
Once the image is downloaded, the browser needs to recalculate the layout and allocate space for the image to fit, which causes other elements on the page to shift.
By providing width and height attributes in the <img> tag, you inform the browser of the image’s aspect ratio. This allows the browser to allocate the correct amount of space in the layout before the image is fully downloaded and prevents any unexpected layout shifts.
Ads Can Cause CLS
If you load AdSense ads in the content or leaderboard on top of the articles without proper styling and settings, the layout may shift.
This one is a little tricky to deal with because ad sizes can be different. For example, it may be a 970×250 or 970×90 ad, and if you allocate 970×90 space, it may load a 970×250 ad and cause a shift.
In contrast, if you allocate a 970×250 ad and it loads a 970×90 banner, there will be a lot of white space around it, making the page look bad.
It is a trade-off, either you should load ads with the same size and benefit from increased inventory and higher CPMs or load multiple-sized ads at the expense of user experience or CLS metric.
Dynamically Injected Content
This is content that is injected into the webpage.
For example, posts on X (formerly Twitter), which load in the content of an article, may have arbitrary height depending on the post content length, causing the layout to shift.
Of course, those usually are below the fold and don’t count on the initial page load, but if the user scrolls fast enough to reach the point where the X post is placed and it hasn’t yet loaded, then it will cause a layout shift and contribute into your CLS metric.
One way to mitigate this shift is to give the average min-height CSS property to the tweet parent div tag because it is impossible to know the height of the tweet post before it loads so we can pre-allocate space.
Another way to fix this is to apply a CSS rule to the parent div tag containing the tweet to fix the height.
#tweet-div { max-height: 300px; overflow: auto; }
However, it will cause a scrollbar to appear, and users will have to scroll to view the tweet, which may not be best for user experience.
If none of the suggested methods works, you could take a screenshot of the tweet and link to it.
Web-Based Fonts
Downloaded web fonts can cause what’s known as Flash of invisible text (FOIT).
A way to prevent that is to use preload fonts
<link rel="preload" href="https://www.example.com/fonts/inter.woff2" as="font" type="font/woff2" crossorigin>
and using font-display: swap; css property on @font-face at-rule.
@font-face { font-family: Inter; font-style: normal; font-weight: 200 900; font-display: swap; src: url('https://www.example.com/fonts/inter.woff2') format('woff2'); }
With these rules, you are loading web fonts as quickly as possible and telling the browser to use the system font until it loads the web fonts. As soon as the browser finishes loading the fonts, it swaps the system fonts with the loaded web fonts.
However, you may still have an effect called Flash of Unstyled Text (FOUT), which is impossible to avoid when using non-system fonts because it takes some time until web fonts load, and system fonts will be displayed during that time.
In the video below, you can see how the title font is changed by causing a shift.
The visibility of FOUT depends on the user’s connection speed if the recommended font loading mechanism is implemented.
If the user’s connection is sufficiently fast, the web fonts may load quickly enough and eliminate the noticeable FOUT effect.
Therefore, using system fonts whenever possible is a great approach, but it may not always be possible due to brand style guidelines or specific design requirements.
CSS Or JavaScript Animations
When animating HTML elements’ height via CSS or JS, for example, it expands an element vertically and shrinks by pushing down content, causing a layout shift.
To prevent that, use CSS transforms by allocating space for the element being animated. You can see the difference between CSS animation, which causes a shift on the left, and the same animation, which uses CSS transformation.
How Cumulative Layout Shift Is Calculated
This is a product of two metrics/events called “Impact Fraction” and “Distance Fraction.”
CLS = ( Impact Fraction)×( Distance Fraction)
Impact Fraction
Impact fraction measures how much space an unstable element takes up in the viewport.
A viewport is what you see on the mobile screen.
When an element downloads and then shifts, the total space that the element occupies, from the location that it occupied in the viewport when it’s first rendered to the final location when the page is rendered.
The example that Google uses is an element that occupies 50% of the viewport and then drops down by another 25%.
When added together, the 75% value is called the Impact Fraction, and it’s expressed as a score of 0.75.
Distance Fraction
The second measurement is called the Distance Fraction. The distance fraction is the amount of space the page element has moved from the original to the final position.
In the above example, the page element moved 25%.
So now the Cumulative Layout Score is calculated by multiplying the Impact Fraction by the Distance Fraction:
0.75 x 0.25 = 0.1875
The calculation involves some more math and other considerations. What’s important to take away from this is that the score is one way to measure an important user experience factor.
Here is an example video visually illustrating what impact and distance factors are:
Understand Cumulative Layout Shift
Understanding Cumulative Layout Shift is important, but it’s not necessary to know how to do the calculations yourself.
However, understanding what it means and how it works is key, as this has become part of the Core Web Vitals ranking factor.
More resources:
Featured image credit: BestForBest/Shutterstock