Elevate Your Site's UX: Pro Tips on Minimizing Cumulative Layout Shift
Tags: javascript, seo, performance, webdev
Published: 2023-12-15 10:58:08

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](#what-is-cumulative-layout-shift)
- [Why it is important](#why-it-is-important)
- [How to improve CLS](#how-to-improve-cls)
- [Recap](#recap)

## What is Cumulative Layout Shift

![Example of cumulative layout shift](https://i.imgur.com/ZjZYyZy.gif)

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](https://cdn.sanity.io/images/vftxng62/production/b2bfe6b9f1d45a40833b37caa571f54a7b4be1c0-2000x1352.png)

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 "jumping" button, source: https://themeisle.com/](https://i.imgur.com/hEiTPyL.gif)

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](https://lookerstudio.google.com/u/0/reporting/55bc8fad-44c2-4280-aa0b-5f3f0cd3d2be/page/M6ZPC?params=%7B%22df44%22:%22include%25EE%2580%25800%25EE%2580%2580IN%25EE%2580%2580ALL%22%7D), 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](https://cdn.sanity.io/images/vftxng62/production/43e60af3563d914a82ef343fa9cf5e9653517ecc-1600x1243.jpg)

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](https://cdn.sanity.io/images/vftxng62/production/f94a42196c39f29bddac6e4e5767c3f0ea0afe1e-2000x1352.png)


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](https://cdn.sanity.io/images/vftxng62/production/8f1672c3f36d8c3c929fe0f20289032000bb129b-1376x250.jpg)

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](https://httparchive.org/reports/state-of-the-web#fontDisplay) to show how many sites prevents FOIT by using font-display

![flash of invisible text report, source httparchive.org](https://cdn.sanity.io/images/vftxng62/production/584c9ff6c623c722e25726aa0be0363e9ff43a5c-1600x1130.jpg)

4. 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](https://cdn.sanity.io/images/vftxng62/production/eb7274070f66e277066fc359678327ab19cac514-1494x774.jpg)

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](https://cdn.sanity.io/images/vftxng62/production/e8121192cb07426473d3e48b8037f30fd833e23e-1436x318.jpg)

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;
}
```

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';
}
```

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