Elevate Your Site's UX: Pro Tips on Minimizing Cumulative Layout Shift

Sergey Labut - Dec 15 '23 - - Dev Community

In this article we will consider one of Core Web Vitals (CWV) – Cumulative Layout Shift (CLS). What is it? Why is it important? And how to improve it?

What is Cumulative Layout Shift

Example of cumulative layout shift

CLS was presented to a broad audience in Chrome Lighthouse by Google around 2020 as one of CWV metrics. After that, we'll learn more about what indicators Google uses to rank search results – CWV are measurable values used by Google to determine the overall performance of a site and this performance impacts search results. CLS specifically is a measure of layout stability. It reflects a largest (was sum previously) content shift – when an element in a viewport changes its starting position between two frames
To be more accurate CLS is a measure of the largest burst of layout shift scores.
A burst of layout shifts, known as a session window, occurs when one or more individual layout shifts happen rapidly, with intervals of less than 1 second between each shift, and within a total window duration of maximum 5 seconds.

Why it is important

Imagine you open a website and as soon as the first block of text appears you start reading it, but then the huge image above loads and pushes all the text down and you have to find the place where you read again. It's very annoying
Many users access the Internet from their smartphones and CLS for those users can be even more noticeable

example of content shift

Another classic example is the unintentional creation of orders.
When the user wants to click the return button but suddenly the advertisment above loads and pushes all the content down and the user clicks the create order button instead.

example of

I am sure, I don't need to explain how bad this is.

Also it's important to mention that this is one of the three CWV, which means it has a big impact on SEO.

In any case, content jumps can lead to user disappointment in your site/product. According to the httparchive.org, most sites have good CLS - another reason to take care of it so as not to stand out for the worse.

core web vitals report, source httparchive.org

Now you know that shift happens. Let's discuss the ways how to avoid it

How to improve CLS

To improve the metric we need to understand how it is measured. Essentially, this is multiplying the size of the content being moved by the distance it was moved:

layout shift score = impact fraction * distance fraction
In the example below, the largest viewport dimension is the height, and the unstable element has moved by 25% of the viewport height, which makes the distance fraction 0.25.
So, in this example the impact fraction is 0.75 and the distance fraction is 0.25, so the layout shift score is 0.75 * 0.25 = 0.1875.

example of content shift

Only unexpected shifts appear in the final score. By unexpected we understand that it was not requested by the user. CSS transform shifts are also ignored.

A good CLS is less than 0.1 but It's important to aim for lower values to enhance user experience, even if it falls under 0.1

CLS specs, source web.dev

Most of the time CLS happens during page load and Chrome Lighthouse can be a good tool to measure CLS in this case.

After the test you will receive some information on how to improve your performance.

Before we dive into this, let's introduce two new terms:

  • flash of invisible text (FOIT) - it is an issue where text remains invisible while webfont is loading – space for text is reserved, just empt;,
  • flash of unstyled text (FOUT) - it is an issue where text is changed because of a big difference of downloaded font and a fallback font, this usually affects the length of the text: the text may become larger or smaller and shifts the content on the page

But here are general causes of CLS:

  1. Image/video suddenly downloaded and shifted all content down. It happens when the image/video has no dimensions: width and height. So browsers did not reserve a space for it.
  2. Dynamic insertion in DOM – by JS script execution
  3. FOIT
  4. FOUT

Ways to reduce CLS:

  1. In the case of images/videos you just need to make sure you added width and height attributes.
  2. In case of dynamic DOM update – you should restrict the size of it and use placeholder maybe, also try to add it below the viewport.
  3. In case of FOIT you should use font-display property The font-display property accepts five values: auto (default): The browser uses its default method for loading, which is most often similar to the block value. block: The browser will hide the text until the web font is fully loaded. But it is hidden in a very specific way - the text seems to be there, but it is not visible. Also known as Flash of invisible text or FOIT. swap: The browser will use local fallback font to display the text until the web font is fully downloaded. Can cause Flash of unstyled text or FOUT. fallback: The browser will hide the text for 100ms, then if the web font is not ready, uses a fallback font, and finally switches to the web font but swap period is less than 3 seconds. optional: The browser will use fallback font and will decide to switch or not to web font considering user's connection speed -- if connection is very slow it can even ignore web font Most of the time to eliminate FOIT you should use swap but swap can possibly lead to FOUT. We will handle it next Here is another chart from httparchive.org to show how many sites prevents FOIT by using font-display

flash of invisible text report, source httparchive.org

  1. In case of shifts due to font differences. You can change the local font (available by default for the user) to be very similar to your web font. For this example we are using this tool https://screenspan.net/fallback We will try to use Arial as fallback for Roboto regular We can adjust font properties manually and see a live preview.

interface of fallback font generator, source https://screenspan.net/fallback

After adjustments, we got a good match between the fonts.The same text, written in Arial and Roboto in different colors for clarity.

font matching results, source https://screenspan.net/fallback

Here are the CSS rules we get

@font-face {
    font-family: 'Adjusted Arial Fallback';
    src: local(Arial);
    size-adjust: 98%;
    ascent-override: 96%;
    descent-override: normal;
    line-gap-override: normal;
}
Enter fullscreen mode Exit fullscreen mode

Then, when listing suitable fonts, use the fallback for Roboto-Regular instead of the local font (Arial in our case).

h1 {
    font-family: 'Roboto-Regular', 'Adjusted Arial Fallback';
}
Enter fullscreen mode Exit fullscreen mode

This should reduce the difference between fonts and reduce CLS or even eliminate it.

Recap

In this article we went through some tips on CLS performance. In conclusion we can note that CLS is a pretty important metric and by paying attention to it we can increase overall user experience on our site and get higher ranking in search results. It should be noted that CLS is measured during the lifespan of the page but it focuses on individual session windows within that lifespan, not the cumulative layout shift across the entire lifespan directly

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .