Imagine you’re waiting for a website to load on your phone. As it loads, you see a button that you want to tap. But just a few milliseconds before your finger meets the screen, the button shifts by half an inch. There was an ad somewhere above the button that suddenly loaded, causing the part of the page below it (including the button) to quickly shift lower.
Ugh! So annoying isn’t it? If your finger tapped on another button by mistake, you’d even be taken to another web page, from where you’d have to go back and wait again for the original page to load.
We’ve all experienced this at least a few times on different websites. The good news is, Google has finally announced Page Experience as a ranking factor on their SERP.
In this article, we shall be talking about one of the factors that contribute to a good page experience, called CLS or Cumulative Layout Shift.
What is Cumulative Layout Shift?
CLS is a metric that shows us the sum total of all the layout shift scores caused by shifts in website layout that happen when a web page loads. In simpler terms, it measures visual stability. These layout shifts happen when an element on the web page changes its position. Just like that button we mentioned above.
You need to optimise your page so that your CLS score is less than 0.1.
How is Layout Shift score calculated?
The part of your browser that displays this webpage, and all other webpages for that matter, is called a viewport. It is the area of the window, through which the web content can be seen.
Now, to calculate the layout shift score, the browser looks at the size of the viewport and the movement of unstable elements between 2 rendered frames.
The layout shift score is a product of 2 things: impact friction and distance friction.
LSS = impact friction x distance friction
What is impact friction?
Impact friction, put in basic terms, is the combined area a moving element takes in 2 frames.
Let’s take an example to understand what that means.
- You’re on a web page on your phone.
- A single element covers 50% of your screen (or viewport, but let’s just assume we have the web page on full screen).
- Suddenly, the layout shifts and the element moves lower. It moves about 25% of the viewport height.
- In the first frame, the element covered 50% of the viewport, and in the second frame, it has moved down to 25% of the viewport height. When you combine both frames (the union of the element’s visible area) you get 75% of the total viewport. Or 0.75.
What is distance friction?
This measures the distance an unstable element has moved, in relation to the viewport.
Let’s take the greatest distance an unstable element has moved (horizontal or vertical), and divide it by the viewport’s largest vertical or horizontal dimension.
So in the above example, the unstable element was said to move 25% lower along the height of the viewport. This makes the distance friction to be 0.25.
Plugging these values into the formula gives:
LSS = 0.75 x 0.25 =0.1875
To explain that to a school kid, layout shift score is a product of the percentage of the area taken by an element as it moves between 2 frames, and the percentage of the height (or width) that it moves between those two frames. Kind of like area multiplied by displacement.
What about dynamic web applications with moving elements?
We know that dynamic web apps often change the start position of elements on the pages. Shouldn’t this affect CLS score too?
A shift in the layout is only considered bad when a user is not expecting it. So if an element on the page moves when a user interacts with your page, it is not included in the CLS calculations. When the layout shifts happen within 500 milliseconds of user input, it will have the hadRecentInput flag set.
Smooth transitions that we see on some sites these days also won’t be included in CLS scores. You should consider using CSS transform properties like transform: scale() and transform: translate() instead of changing the height, width, top, right, bottom, etc properties.
How to measure CLS?
You can use tools like PageSpeed Insights, Chrome User Experience Report, Lighthouse and more to test and measure CLS scores.
How to improve the CLS score?
Here are some ways that you can keep your CLS scores as low as possible:
- Include size attributes on your images/video elements.
- Or reserve the space required for those elements. You can use CSS aspect ratio boxes. Kind of like placing a “reserved” card on a seat.
- Stop inserting content above the existing content.
- Like mentioned above, use CSS transform animations. The transitions must not confuse users and should not be abrupt.
- You should include width and size attributes on your images and video elements.
- Reserve slot size allotted for ads.
- To avoid leaving a blank space or collapsing the reserved space whenever an ad doesn’t load, leave a placeholder.
- There could be a possibility of the ad being larger than the space you’ve reserved for them. You will need to check the historical data of the sizes of the ads that have appeared in that area, and then choose the most possible size for the ad space.
Downloading and rendering web fonts can also cause layout shifts. These can appear in two different ways:
FOUT – Flash of Unstyled Text
Browsers might display a fallback font until the custom font loads. This is called “Flash of Unstyled Text”. Not only is it visually unsettling, but it also causes layout shifts.
FOIT – Flash of Invisible Text
In this case, the text would be invisible until the custom font had loaded. This is called “Flash of Invisible Text”. This affects render time performance and your website visitors will be looking at large spaces of emptiness. This can be fixed by ensuring that the text is loaded using a system font. Once the custom font is ready, it can replace the system fonts. But this can still cause layout issues like FOUT does.
Another fix is to pre-load custom fonts. This also increases page loading speed, which also boosts your rankings!
There’s a CSS font-display property that you can use to modify how custom fonts render. You can do this with a range of different values. font-display: optional behaves just like FOUT in the sense, there is a fallback font involved. But here, the browser can decide whether to show the custom font or not depending on a user’s connection speed.
It uses a timeline of three periods that need to be downloaded before they can be rendered.
Block: Renders invisible text.
Swap: Renders text in fallback system font, but shift to custom fonts as soon as they have loaded.
Fail: Render text only using a fallback system font.
There used to be a time when fonts designated like this has a 100ms block period and no swap period. What this means is that:
- Invisible text is displayed before switching to a fallback system font.
- If the custom font loads within 100ms, swapping occurs and the custom font is displayed.
- If the custom font fails to load within 100ms, no swapping occurs and the text is displayed in the fallback system font itself.
But in this case, there is still a slight flicker or a layout shift when text shifts from invisible to fallback or custom font.
However, in Chrome 83, a few optimizations have altogether removed the first render cycle for optional fonts which are preloaded with <link rel=”preload”>. In this case, rendering is blocked until the custom font has finished loading within 100ms. If it does, the custom font is rendered, or else, the fallback font is rendered. The difference is, there’s no invisible text like in the previous case. This prevents any layout shift.
So that’s pretty much all you need to know about CLS. For now at least. Expect more content from us as we find more information on Core Web Vitals. Subscribe to our newsletter if you haven’t already.
Have you started optimising your web pages for better Page Experience yet? You probably should start right away. Contact our team of web developers if you need any help.