DEV Community

Cover image for Measuring Cumulative Layout Shift (CLS) in WebPageTest
Rick Viscomi for Google Web Dev

Posted on • Updated on

Measuring Cumulative Layout Shift (CLS) in WebPageTest

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? 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.

    // Send the final score to your analytics back end
    // (assumes `sendToAnalytics` is defined elsewhere).
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:

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:

return new Promise(resolve => {
  var CLS = 0;
  new PerformanceObserver(list => {
    list.getEntries().forEach(entry => {
      if (entry.hadRecentInput) return;
      CLS += entry.value;
  }).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.

Top comments (11)

shailenderjain profile image
Shailender Jain

I want to check the value for my site
I run the site against 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

rick_viscomi profile image
Rick Viscomi

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.

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)?

vamshi profile image
vamshi • Edited

I always check only performance score on the PageSpeed Insights for my websites, and After reading this article I also inspect the Cumulative Layout Shift (CLS) values for web and mobile versions of my websites. Thanks for the article.

jabbar_mughal_ea3cfa760fb profile image
Jabbar Mughal

I used to focus solely on the performance score when checking my websites, and and more using PageSpeed Insights. However, after reading this enlightening article, I have also started paying attention to the Cumulative Layout Shift (CLS) values for both web and mobile versions of these sites. Thanks for sharing this valuable information!

dkranker profile image

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?

garrettn profile image
Garrett Nafzinger

This was quite helpful and well documented. Thank you!

bobbyiliev profile image
Bobby Iliev

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

rick_viscomi profile image
Rick Viscomi

Thanks, I'm glad to hear that!

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

Awesome! Thanks!

Some comments may only be visible to logged-in visitors. Sign in to view all comments.