DEV Community

loading...
Cover image for Measuring Cumulative Layout Shift (CLS) in WebPageTest
Google Web Dev

Measuring Cumulative Layout Shift (CLS) in WebPageTest

Rick Viscomi
I work on web transparency projects like the HTTP Archive and Chrome UX Report. I work towards a faster, better web for everyone.
Updated on ・3 min read

What is CLS?

Cumulative Layout Shift (CLS) is a relatively new metric to help you understand the delightfulness of the user experience. You might be reading a website when suddenly the text shifts down 100 pixels and you lose your place. That's not a delightful experience.

A graphic showing text shifting down

The value of a layout shift is the percent of the viewport that moved. So in this example perhaps 10% of the viewport shifted. If another shift of 2% happens later, the page's CLS would be 12%.

How can it be measured?

web.dev/layout-instability/api is a great resource to learn more about the API and how to use it to measure CLS. Here's their example code to calculate CLS:

// Stores the current layout shift score for the page.
let cumulativeLayoutShiftScore = 0;

// Detects new layout shift occurrences and updates the
// `cumulativeLayoutShiftScore` variable.
const observer = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    cumulativeLayoutShiftScore += entry.value;
  }
});

observer.observe({entryTypes: ['layoutShift']});

// Sends the final score to your analytics back end once
// the page's lifecycle state becomes hidden.
document.addEventListener('visibilitychange', () => {
  if (document.visibilityState === 'hidden') {
    // Force any pending records to be dispatched.
    observer.takeRecords();

    // Send the final score to your analytics back end
    // (assumes `sendToAnalytics` is defined elsewhere).
    sendToAnalytics({cumulativeLayoutShiftScore});
  }
});
Enter fullscreen mode Exit fullscreen mode

At the moment, the layoutShift type is only available when the API is explicitly enabled. If you're running Chrome 76 or newer, you can start it up via the command line with this flag set:

--enable-blink-features=LayoutInstabilityAPI
Enter fullscreen mode Exit fullscreen mode

Measuring CLS in WebPageTest

WebPageTest (WPT) is a popular tool for controlled measurements of web performance stats. Let's take a look at how we can configure it to record CLS.

Choosing the right browser

WPT supports many browsers from many locations around the world. For this test to work, we need a newer version of Chrome that supports the LayoutInstabilityAPI Blink feature. Since WPT's default version of Chrome is on version 75 at this time of writing, we'll select Chrome Canary (version 77), which is available from the Dulles, VA test location.

Setting the command line flag

Under the advanced settings "Chromium" tab there's a field to provide command line options.

Measuring CLS as a custom metric

Custom metrics are snippets of JavaScript that execute as the web page test is wrapping up. The syntax is to give it a name in [name] format on the first line, followed by a script with a single return value. Here's a custom metric to measure CLS:

[CumulativeLayoutShift]
return new Promise(resolve => {
  var CLS = 0;
  new PerformanceObserver(list => {
    list.getEntries().forEach(entry => {
      if (entry.hadRecentInput) return;
      CLS += entry.value;
    });
    resolve(CLS);
  }).observe({type: "layout-shift", buffered: true});
});
Enter fullscreen mode Exit fullscreen mode

Side note: Astute WPT mega-pro power users reading this post are objecting to this script because it returns a promise, and custom metrics only support synchronous code. Not anymore! As of literally a couple hours ago, WPT now supports async custom metrics!

This script will resolve to the CLS value for the test page, whose layout shifts have been saved to a buffer.


Ok! So with those options configured, you're ready to enter the URL of the page you want to test and run it. You can find the results on the Custom Metrics page.

For this page, the CLS is 0.3. It's a page I built, with a large part of its UI dynamically rendered from a script, so ~30% checks out.

To visualize this, we can use the filmstrip view, which shows us what the page looked like while it loaded. In this case it was blank for half a second, then the entire thing rendered. It's not clear where the layout shift is, but it could have happened in a matter of milliseconds. It isn't necessarily a poor user experience if the layout shift happens so close to the start of rendering, so that might be a case for tweaking the CLS algorithm.

Wrapping up

CLS is still a very new metric, so if you do start using it, please leave any feedback on the Layout Instability API GitHub repository.

Discussion (9)

Collapse
shailenderjain profile image
Shailender Jain

I want to check the value for my site miniimagesvideos.com/
I run the site against developers.google.com/speed/pagesp.... Field value is coming as 0.26, while the lab value is coming as 0.0. I have embed the script in my html pages and keep getting the value as 0. Is there any site which can measure accurately

Collapse
rick_viscomi profile image
Rick Viscomi Author

This is a great question and one of the challenges of measuring CLS in the lab.

Field data is inclusive of all of the actions users take on the website like scrolling and interacting with buttons. CLS may be occurring in these kinds of scenarios that lab tools like WebPageTest and Lighthouse don't currently simulate by default. With CLS gaining popularity as a Core Web Vital metric, I'd love to see lab tools incorporate more user-like behaviors to be comparable with field data.

Collapse
imkevdev profile image
Kevin Farrugia

Web Vitals come from CrUX, does this mean that CLS should be tested as a repeat visitor if most traffic is for repeat visitors? The same applies for cookie popups, which only appear on first visit, should WPT be tested with the cookies set (to disable the popup)?

Collapse
dkranker profile image
dkranker

One of the solutions I've been seeing for improving CLS is to use img { aspect-ratio: attr(width) / attr(height);}. However, I'm seeing aspect-ratio as not supported when I inspect in chrome for any use I've tried. Could anyone provide any insight on this?

Collapse
garrettn profile image
Garrett Nafzinger

This was quite helpful and well documented. Thank you!

Collapse
bobbyiliev profile image
Bobby Iliev

Great tutorial! It helped me a lot today! Well done!

Collapse
rick_viscomi profile image
Rick Viscomi Author

Thanks, I'm glad to hear that!

Collapse
vigodnee profile image
Алексей Махметхажиев

Awesome! Thanks!

Collapse
internettegentr profile image
internettegentr • Edited

My site name is internette.gen.tr/ No cls problem in my site for google page speed. "0" cls problem in site. İts very good site. But Search Console say me your site is worth and you have cls problem.

Which is correct?

page speed in : page speed internette

in attach look reds urls.

dev-to-uploads.s3.amazonaws.com/i/...