1. Introduction

Cumulative Layout Shift (CLS), which translates to Cumulative Layout Shift. It is an important user-centric measure of the stability of visual area elements. It can help us quantify how often users encounter unexpected layout offsets. CLS is small to ensure that our pages have a good user experience.
Have you ever read an article online and suddenly the page in front of you changes, without warning, and the content you were reading just goes nowhere? Even worse, you might be about to click on a link or button, and as soon as you click, the link or button changes position and you end up clicking somewhere else! Most of the time the experience is just unpleasant, but sometimes it’s more than that.
Unexpected movement of content in web pages is often caused by asynchronously loading resources or dynamically adding DOM elements to the current page. The culprit may be
  1. Pictures or videos of unknown size
  2. Render fonts that are actually larger or smaller than their original size
  3. Third party ads or page widgets that can dynamically resize themselves
  4. .
To make this problem even more difficult, the functionality of the site varies greatly between the development environment and the actual user experience. Personalized and the content of the third party in the development environment and online environment are often inconsistent performance, for example, used to do the test images in most cases are cached in the browser developers, in addition, local call apis are generally more quickly, so that some of the online environment likely delay was ignored by developers in the development stage.
CLS can help you solve these problems by measuring how often real online users encounter these problems.

2. What is CLS

The CLS calculates the total score for all unexpected layout offsets that occur over the life of the page.
Every time a visual element changes position, a layout offset occurs.

So what makes a good CLS score?
A site with a good user experience should have a CLS score of less than 0.1 as far as possible. To ensure that this score is achieved for most users, at least 75% of total page views on mobile and desktop devices should be measured.

3. Look at layer transformations in detail

The concept Layout migration is in [Layout Instability API] defined (https://github.com/WICG/layout-instability), The API reports a layout offset whenever a visible element in the viewport changes its original position, Such as in the default/write mode (https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode) under its top and left, elements are regarded as unstable elements like this.
Note that a layout offset occurs only when the visual element changes its original position. If a new element is added to the DOM or a visual element changes its size, it is not considered a layout offset, meaning that the change that occurred does not cause the visual element to change its original position is not considered a layout offset.

4. Layout offset score

The browser calculates the layout offset score based on the viewport size and the displacement of unstable elements between frames. The final score is the product of the two measurement dimensions of the displacement, namely the influence score and the distance score.
layout shift score = impact fraction * distance fraction
Copy the code

5. Affect grades

The influence score measures the extent to which an unstable element affects the viewport from the last frame to the next.
The influence score of the current frame is the sum of the visual area occupied by all unstable elements in the viewport from the previous frame to the current frame.

As you can see from the figure above, the first frame element takes up half of the viewport height, and the next frame element moves down 25% of the viewport height. The red box identifies the total viewable area the element occupies in the two frames. This value is 75% of the viewport height, so the impact score is 0.75.

6. Distance score

Another part of the CLS formula is the distance score, which measures how far an unstable element moves relative to the viewport. The specific calculation method is as follows:
Distance score = the maximum distance the unstable element can move vertically or horizontally, whichever is greater/the maximum size of the viewport (width or height, whichever is greater)

In the example above, the maximum size of the viewport is in height, and the unstable element moves down 25% of the viewport height in the viewport, with a distance score of 0.25.
In this example the impact score is 0.75 and the distance score is 0.25, so the final CLS score is 0.75 * 0.25 = 0.1875.
Initially, CLS calculations were based solely on impact scores. The distance fraction is introduced to avoid large CLS calculated by small displacement of large size elements.
The following example illustrates how adding content to an existing element affects CLS.

The “Click Me” button was added to the bottom of the gray box above, causing the green box below to move down and part of the content to go beyond the viewport.
The size of the gray box has increased, but the starting position has not changed, so it cannot be considered unstable.
The “Click Me” button does not originally exist in the DOM, so there is no way to say whether its starting position changes or not, and it cannot be considered unstable.
For the green box, its starting position has indeed changed, but because part of its content has moved out of the viewport, and the invisible area cannot participate in the calculation of the influence score, so between the two frames, the part of the green box that participates in the calculation of the influence score is only the part of the red box above. This part is the same size as the green box in the first frame, which is 50% of the viewport, so the final impact score is 0.5.
The distance score is calculated from the part marked by the purple arrow above. The green box moves down about 14% of the viewport height, so the distance score is 0.14.
The CLS of the final view is 0.5 x 0.14 = 0.07.
The above examples are for a single unstable element. Now let’s see how CLS is calculated for multiple unstable elements

In the first frame, four animals are retrieved from the API return, and they are arranged in alphabetical order. In frame two, there are other animals in the list.
The starting position of Cat does not change between frames, so it is a stable element. Similarly, all new elements are stable elements. But the starting position of “Dog,” “Horse,” and “Zebra” all changed, so all three elements were unstable.
The red box area is the sum of the visual area occupied by the three unstable elements between frames. The old position of “Dog” plus the new position gives a total of two Li’s. The same goes for “Horse” and “Zebra”. In theory, they should end up with six Li’s, but it’s important to note that the new location of “Dog” actually occupies the old location of “Horse”, so you end up with five Li’s subtracted from this one.
The above arrows represent the distance traveled by the three unstable elements. The blue arrow represents the distance traveled by the “Zebra”, which is approximately 30% of the viewport height and is the maximum distance traveled, so the distance score for the above example is 0.3.
The final CLS score is 0.38 x 0.3 = 0.1172.

7. Expected layout offsets vs. unexpected layout offsets

Not all layout offsets are negative. In fact, many dynamic web applications often modify the initial placement of elements.

7.1 User-led Layout Offset

Layout offsets are negative only if they occur unexpectedly, whereas layout offsets that occur in response to user interactions (clicking links, clicking buttons, or entering content into an input box) are generally positive. As long as the layout offset occurs close enough to the interaction that the user can clearly see the relationship between the two.
For example, if a user invokes a network request that may take a while to complete, it is good practice to add a loading effect to avoid unpleasant layout offsets that occur after the request ends. If the user is unaware that the page is loading something, or does not know when the requested resource will be ready, he may try to click on something else in the meantime, and that content may move down after the requested resource arrives.
Within 500 milliseconds of user input with the layout of the migration will sign [hadRecentInput] (https://wicg.github.io/layout-instability/#dom-layoutshift-hadrecentinput), This field can be used to exclude it from the calculation.

7.2 Animation and Transitions

Animations and transitions, when used well, can update the page without the user feeling jarred. A sudden and unexpected layout deviation on a page can lead to an unfriendly user experience in most cases. However, if the content moves naturally and smoothly from one location to another, it will help the user understand the changes that are taking place and guide the user.
CSS (transform) (https://developer.mozilla.org/en-US/docs/Web/CSS/transform) allows you to set the animation to elements, and does not cause offset layout, the following is the specific method of use:
  • Use the transfom: Scale () instead of width and height to change the element size
  • When moving elements, avoid changing the top, right, bottom, and left attributes. Use transform: Translate () instead.

8. How is CLS measured

CLS can be measured in the development phase or in the live line. Some of the tools available are listed below
Note: The development phase is not a substitute for the online environment after all, as we usually only load the page during development, so the CLS value reported to the page by these tools may be lower than the ONLINE CLS value.

8.1 On-line measurement tools

  • [Chrome User Experience Report](https://developers.google.com/web/tools/chrome-user-experience-report)
  • [PageSpeed Insights](https://developers.google.com/speed/pagespeed/insights/)
  • [Search Console (Core Web Vitals report)](https://support.google.com/webmasters/answer/9205520)

8.2 Develop measurement tools

  • [Chrome DevTools](https://developers.google.com/web/tools/chrome-devtools/)
  • [Lighthouse](https://developers.google.com/web/tools/lighthouse/)
  • [WebPageTest](https://webpagetest.org/)

8.3 Using JavaScript to measure CLS

The easiest way to measure CLS (and all the other important online metrics on the Web) is to use the Web-Vitals JavaScript library, which encapsulates all the complexity points we need to manually measure CLS in a single function:
import {getCLS} from 'web-vitals'; // Measure and log the current CLS value,
// any time it's ready to be reported.
getCLS(console.log); 
Copy the code

CLS to manual measurement, you can use [Layout Instability API] (https://github.com/WICG/layout-instability). The following example shows how to create a PerformanceObserver to listen for individual instances of layout offsets and log them to the console:
// Use a try/catch instead of feature detecting `layout-shift` // support, since some browsers throw when using the new `type` option. // https://bugs.webkit.org/show_bug.cgi?id=209216 try { const po = new PerformanceObserver((list) => { for (const entry of list.getEntries()) { console.log(entry); }}); po.observe({ type: 'layout-shift', buffered: true }); } catch (e) { // Do nothing if the browser doesn't support this API. }Copy the code

CLS is the sum of [all layout offsets that occurred] after removing [layout offsets that occurred with the most recent user input], so to compute THE CLS, you need to declare a variable that stores the current CLS score and then increment it when new layout offsets are detected.

Rather than reporting every CLS change, it is better to track the current CLS value and report when the page’s life cycle state becomes hidden, because such CLS changes can be very frequent, and frequent reporting can cause performance problems.
html

<! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, /> <title>Document</title> <style> * {padding: 0; margin: 0; } .box { position: absolute; left: 0; top: 0; The transition: all 0.2 s linear; width: 300px; height: 300px; background: blue; } .active { top: 100px; } < / style > < / head > < body > < div id = "box" class = "box" > I am a box < / div > < script SRC = ". / CLS. Js "> < / script > < script > setTimeout (()  => { document.getElementById('box').classList.add('active'); }, 2000); </script> </body> </html>Copy the code
js
// Sends the passed data to an analytics endpoint. This code
// uses `/analytics`; you can replace it with your own URL.
function sendToAnalytics(data) {
const body = JSON.stringify(data);
console.log(body);
// Use `navigator.sendBeacon()` if available, falling back to `fetch()`.
// (navigator.sendBeacon && navigator.sendBeacon('/analytics', body)) ||
// fetch('/analytics', { body, method: 'POST', keepalive: true });
}
// Use a try/catch instead of feature detecting `layout-shift`
// support, since some browsers throw when using the new `type` option.
// https://bugs.webkit.org/show_bug.cgi?id=209216
try {
// Store the current layout shift score for the page.
let cls = 0;
function onLayoutShiftEntry(entry) {
console.log(entry);
// Only count layout shifts without recent user input.
if (!entry.hadRecentInput) {
cls += entry.value;
}
}
// Create a PerformanceObserver that calls `onLayoutShiftEntry` for each entry.
const po = new PerformanceObserver((entryList, po) => {
entryList.getEntries().forEach((entry) => onLayoutShiftEntry(entry, po));
});
// Observe entries of type `layout-shift`, including buffered entries,
// i.e. entries that occurred before calling `observe()` below.
po.observe({
type: 'layout-shift',
buffered: true,
});
// Log the current CLS score any time the
// page's lifecycle state changes to hidden.
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'hidden') {
// Include any pending records not yet dispatched,
// and send the CLS value to an analytics endpoint.
po.takeRecords().forEach((entry) => onLayoutShiftEntry(entry, po));
sendToAnalytics({ cls });
}
});
} catch (e) {
console.log(e);
// Do nothing if the browser doesn't support this API.
}
Copy the code

9. How to improve CLS

For most sites, unexpected layout deviations can be avoided by following a few principles:
  • Always set sizing properties on image and video elements, or reserve the space you need through [CSS Aspect Ratio boxes](https://css-tricks.com/aspect-ratio-boxes/). This ensures that the browser allocates the correct space in the document when it loads the image. Alternatively, the [unsized-media feature can be used policy](https://github.com/w3c/webappsec-feature-policy/blob/master/policies/unsized-media.md) Feature policy enforces this behavior in browsers that support feature policy.
  • Never insert content above existing content unless in response to a user interaction to ensure that any layout shifts are expected.
  • Animations are better with transitions than with properties like top and left. Animating transitions provides continuity of context between states.
Original text: [https://web.dev/cls/?utm_source=devtools] (https://web.dev/cls/?utm_source=devtools)