<span style="font-weight: 400;">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. </span>

<span style="font-weight: 400;">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. </span>

<span style="font-weight: 400;">We’ve all experienced this at least a few times on different websites. The good news is, </span><a href="https://vividreal.com/google-page-experience-and-why-you-shouldnt-ignore-it/"><span style="font-weight: 400;">Google has finally announced Page Experience as a ranking factor</span></a><span style="font-weight: 400;"> on their SERP.</span>

<span style="font-weight: 400;">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.</span>

<span style="color: #00ccff;"><b>What is Cumulative Layout Shift?</b></span>

<span style="font-weight: 400;">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.</span>

<span style="font-weight: 400;">You need to optimise your page so that your CLS score is less than 0.1. </span>

<span style="color: #00ccff;"><b>How is Layout Shift score calculated?</b></span>

<span style="font-weight: 400;">The part of your browser that displays this webpage, and all other webpages for that matter, is called a </span><b>viewport</b><span style="font-weight: 400;">. It is the area of the window, through which the web content can be seen.</span>

<span style="font-weight: 400;">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.</span>

<span style="font-weight: 400;">The layout shift score is a product of 2 things: impact friction and distance friction.</span>
<p style="text-align: center;"><em><strong>LSS = impact friction x distance friction</strong></em></p>
<span style="color: #00ccff;"><b>What is impact friction?</b></span>

<span style="font-weight: 400;">Impact friction, put in basic terms, is the combined </span><b>area</b><span style="font-weight: 400;"> a moving element takes in 2 frames.</span>

<span style="font-weight: 400;">Let’s take an example to understand what that means.</span>
<ul>
 	<li style="font-weight: 400;"><span style="font-weight: 400;">You’re on a web page on your phone.</span></li>
 	<li style="font-weight: 400;"><span style="font-weight: 400;">A single element covers 50% of your screen (or viewport, but let’s just assume we have the web page on full screen).</span></li>
 	<li style="font-weight: 400;"><span style="font-weight: 400;">Suddenly, the layout shifts and the element moves lower. It moves about 25% of the viewport height.</span></li>
 	<li style="font-weight: 400;"><span style="font-weight: 400;">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 </span><b>0.75</b><span style="font-weight: 400;">.</span></li>
</ul>
<span style="color: #00ccff;"><b>What is distance friction?</b></span>

<span style="font-weight: 400;">This measures the </span><b>distance</b><span style="font-weight: 400;"> an unstable element has moved, in relation to the viewport.</span>

<span style="font-weight: 400;">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.</span>

<span style="font-weight: 400;">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 </span><b>0.25</b><span style="font-weight: 400;">.</span>

<span style="font-weight: 400;">Plugging these values into the formula gives:</span>
<p style="text-align: center;"><em><b>LSS = 0.75 x 0.25 =0.1875 </b></em></p>
<span style="font-weight: 400;">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.</span>

<span style="color: #00ccff;"><b>What about dynamic web applications with moving elements?</b></span>

<span style="font-weight: 400;">We know that dynamic web apps often change the start position of elements on the pages. Shouldn’t this affect CLS score too?</span>

<span style="font-weight: 400;">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 </span><i><span style="font-weight: 400;">hadRecentInput</span></i><span style="font-weight: 400;"> flag set.</span>

<span style="font-weight: 400;">Smooth transitions that we see on some sites these days also won’t be included in CLS scores. You should consider using CSS </span><i><span style="font-weight: 400;">transform</span></i><span style="font-weight: 400;"> properties like </span><i><span style="font-weight: 400;">transform: scale()</span></i><span style="font-weight: 400;"> and </span><i><span style="font-weight: 400;">transform: translate()</span></i><span style="font-weight: 400;"> instead of changing the </span><i><span style="font-weight: 400;">height, width, top, right, bottom,</span></i><span style="font-weight: 400;"> etc properties.</span>

<span style="color: #00ccff;"><b>How to measure CLS?</b></span>

<span style="font-weight: 400;">You can use tools like PageSpeed Insights, Chrome User Experience Report, Lighthouse and more to test and measure CLS scores. </span>

<span style="color: #00ccff;"><b>How to improve the CLS score?</b></span>

<span style="font-weight: 400;">Here are some ways that you can keep your CLS scores as low as possible:</span>
<ul>
 	<li style="font-weight: 400;"><span style="font-weight: 400;">Include size attributes on your images/video elements.</span></li>
 	<li style="font-weight: 400;"><span style="font-weight: 400;">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.</span></li>
 	<li style="font-weight: 400;"><span style="font-weight: 400;">Stop inserting content </span><span style="font-weight: 400;">above</span><span style="font-weight: 400;"> the existing content. </span></li>
 	<li style="font-weight: 400;"><span style="font-weight: 400;">Like mentioned above, use CSS transform animations. The transitions must not confuse users and should not be abrupt.</span></li>
 	<li style="font-weight: 400;"><span style="font-weight: 400;">You should include </span><i><span style="font-weight: 400;">width</span></i><span style="font-weight: 400;"> and </span><i><span style="font-weight: 400;">size</span></i><span style="font-weight: 400;"> attributes on your images and video elements.</span></li>
 	<li style="font-weight: 400;"><span style="font-weight: 400;">Reserve slot size allotted for ads.</span></li>
 	<li style="font-weight: 400;"><span style="font-weight: 400;">To avoid leaving a blank space or collapsing the reserved space whenever an ad doesn’t load, leave a placeholder.</span></li>
 	<li style="font-weight: 400;"><span style="font-weight: 400;">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.</span></li>
</ul>
<span style="font-weight: 400;">Downloading and rendering web fonts can also cause layout shifts. These can appear in two different ways:</span>

<span style="color: #00ccff;"><b>FOUT - Flash of Unstyled Text</b></span>

<span style="font-weight: 400;">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. </span>

<span style="color: #00ccff;"><b>FOIT - Flash of Invisible Text</b></span><span style="font-weight: 400;">
</span>

<span style="font-weight: 400;">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.</span>

<span style="font-weight: 400;">Another fix is to pre-load custom fonts. This also increases page loading speed, which also boosts your rankings! </span>

<span style="font-weight: 400;">There’s a CSS </span><i><span style="font-weight: 400;">font-display</span></i><span style="font-weight: 400;"> property that you can use to modify how custom fonts render. You can do this with a range of different values. </span><i><span style="font-weight: 400;">font-display: optional</span></i><span style="font-weight: 400;"> behaves just like FOUT in the sense, there is a fallback font involved. But here, the browser </span><b>can decide whether to show the custom font or not</b><span style="font-weight: 400;"> depending on a user’s connection speed. </span>

<span style="font-weight: 400;">It uses a timeline of three periods that need to be downloaded before they can be rendered.</span>

<b>Block</b><span style="font-weight: 400;">: Renders invisible text. </span>

<b>Swap</b><span style="font-weight: 400;">: Renders text in fallback system font, but shift to custom fonts as soon as they have loaded.</span>

<b>Fail</b><span style="font-weight: 400;">: Render text only using a fallback system font.</span>

<span style="font-weight: 400;">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:</span>
<ul>
 	<li style="font-weight: 400;"><span style="font-weight: 400;">Invisible text is displayed before switching to a fallback system font.</span></li>
 	<li style="font-weight: 400;"><span style="font-weight: 400;">If the custom font loads within 100ms, swapping occurs and the custom font is displayed.</span></li>
 	<li style="font-weight: 400;"><span style="font-weight: 400;">If the custom font fails to load within 100ms, no swapping occurs and the text is displayed in the fallback system font itself.</span></li>
</ul>
<span style="font-weight: 400;">But in this case, there is still a slight flicker or a layout shift when text shifts from invisible to fallback or custom font.</span>

<span style="font-weight: 400;">However, in Chrome 83, a few optimizations have altogether removed the first render cycle for optional fonts which are preloaded with &lt;link rel=”preload”&gt;. 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.</span>

<span style="font-weight: 400;">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. </span>

<span style="font-weight: 400;">Have you started optimising your web pages for better Page Experience yet? You probably should start right away. </span><a href="https://vividreal.com/web-development/"><span style="font-weight: 400;">Contact our team of web developers</span></a><span style="font-weight: 400;"> if you need any help.</span>