Cumulative Layout Shift (CLS) and Ads
The web and its standards are constantly changing. It is no wonder that Google also updates its tools to help publishers give their visitors the best user experience.
With Cumulative Layout Shift (CLS), Google introduced a new check that can impact publishers using ads. So I looked into this topic and solutions for our users.
What are Cumulative Layout Shifts?
Contents
Cumulative Layout Shifts (CLS) are part of the Web Vitals, a collection of metrics that aim for a better user experience. Google announced that starting in May 2021, the web vitals score will impact your site’s ranking in the search results.
While experienced publishers know most parts of the web vitals already, like page speed, Cumulative Layout Shift is a new metric.
CLS considers the movement of elements in the visible area (aka “viewport”) of your website. Whenever a visible element changes its start position, a layout shift is happening. It doesn’t matter whether this happens on the entry screen the user sees when loading the page or when they later scroll down. Shifts that are not visible to the user, are not counted.
Tests are done for mobile as well as for desktop devices.
Example of a text with a changing start position due to an element that is injected with a delay.
The main idea is to prevent bad user experiences on websites that constantly shift around. Such behavior could lead to unintended clicks on actionable elements like navigations, buttons, or ads.
To prevent this. CLS focuses on the areas that shift around and the distance they are moving.
Speed doesn’t matter for the CLS score. Even if the shift happens so quickly that the user doesn’t even have a chance to click on an element they didn’t want to click. On the other hand, elements that shift because of intended user interaction are not causing a negative score.
How to measure Cumulative Layout Shift?
There are three tools I’d recommend to measure Web Vitals. Be aware that they tend to give slightly different results.
- Visit PageSpeed Insights to measure the Cumulative Layout Shift or other Web Vitals for any website that is available online. This is the tool I’d recommend you to use if you never measured Cumulative Layout Shift before.
- If you connected your site with the Google Search Console, then navigate to Core Web Vitals to find potential issues the Google crawler found for your site.
- While developing, I am using the Lighthouse test in Chrome. You can find them as a tab in the developer tools. They allow me to quickly run the tests on any website and see how changes affect them. The downside is that the results could vary significantly from the other tools when you are logged in to your site and use browser cache.
Update: I found a few more helpful tools after originally publishing this article:
- https://webvitals.dev/cls visualizes the shifting elements and lists them.
- This Chrome extension allows you to see when a negative CLS score is measured. It lacks the ability to highlight the element but is the closest to a non-technical tool to identify check for trigger points while scrolling. You must enable the overlay option in the extension settings.
- In the Chrome browser itself, open the dev tools options, select More Tools > Rendering > Layout Shift Regions. It highlights shifting regions on the visited sites.
How is the Cumulative Layout Shift score calculated?
The Cumulative Layout Shift score is a product of two changes:
- the area affected by the changes (aka “impact fraction”)
- the distance that changing elements move (aka “distance fraction”)
Taking both factors into account ensures that huge elements are not overly penalized for moving just a bit.
I find it surprising that the distance fraction is calculated based on width or height, whatever is greater. So the calculated impact on the score is smaller on desktop monitors or any other device in landscape than in portrait mode.
Another important factor you need to be aware of is that the CLS score bases on moving (aka “unstable”) elements in the DOM. Elements that inject later do not count themselves, e.g., the area they are populating does not count as “impact fraction.” Only the content they are pushing down is relevant.
You can learn more about how the CLS score is calculated with examples on the web vitals homepage.
What impact does the Cumulative Layout Shift score have?
With 15%, Cumulative Layout Shift has a middle impact on the overall web vitals performance score.
Performance score weights in Lighthouse 6
The score of each audit is converted into a metric from 0 to 100.
To provide a good user experience, sites should strive to have a CLS score of less than 0.1.
https://web.dev/cls/
When you play a bit with the Lighthouse Scoring calculator, you will see that a value of 0.06 in the CLS audit still earns you a score of 100. A value of 0.3, which is still considered “good”, gives you a score of 91 if all the other metrics score perfectly.
Even though the Cumulative Layout Shift has only a small impact on the overall performance score, improving your CLS score to something above 90 is an easy win since it does not require you to change your site’s backbone, the hosting package. A good frontend developer can implement all necessary changes.
How to prevent a bad Cumulative Layout Shift score?
Once you understand what Cumulative Layout Shifts are, it is easy to spot and fix a bad score.
First, you should focus on the elements positioned above the fold, since this is the area most visitors will see. Use the tools mentioned above to identify shifting elements.
Second, try to prevent content that loads or shifts the layout after the basic page layout is loaded. With content that needs time to load, try to reserve the space. Use (inline)-CSS to do this. We have a few solutions related to ads listed below.
Third, try to get your score below 0.1 and be realistic about reaching 0.0. As shown above, a score of 0.03 also counts as perfect. Fixing that last bit doesn’t always justify the costs.
Quick wins are either removing the elements that cause the shift, specifying the height, or moving them down so that they affect a smaller percentage of the viewport.
CLS and Advanced Ads features
Please find a few hints about features in Advanced Ads and their impact on Cumulative Layout Shifts.
Before working on your ad setup, make sure to test the CLS without any ads enabled above the fold to see the optimal score your site can reach by following the measures below.
Responsive AdSense ads or other ad networks
Naturally, any ad codes you receive from ad networks that don’t have a specific height will cause a layout shift even if they load extremely fast, like AdSense ads. This also applies to ad codes from Google Ad Manager.
Follow the CSS examples below to reserve a fixed height for the placement or replace the ad unit with one that comes with a fixed size, like a Medium Rectangle ad unit for AdSense.
Cache-busting
Placements that use passive or AJAX cache-busting create a layout shift. You can actively disable cache-busting for the placements above the fold or set up these placements to not need cache-busting according to the information given in the Cache Busting manual.
Quick tip: you don’t need cache-busting if you deliver the same ad unit to all visitors and devices in the placement above the fold.
Alternatively, follow the instructions in the How to reduce Cumulative Layout Shift section below.
Lazy Loading ads
When using Lazy Load for ads, you can use the additional option to load ads before they reach your viewport. E.g., instead of “0”, set the value to “200” or higher. This will prevent a layout shift in the visible area of the screen and therefore not be considered for the CLS score.
Custom Position & Above Headline placement
The Custom Position and Above Headline placements in Advanced Ads Pro are placed dynamically on your website and don’t reserve any space. So they naturally create a layout shift.
To solve this, you can
- use the information below to set the height of the parent element
- replace the placements above the fold with another option mentioned in this tutorial or move them into your site’s content
Ad Slider
The Ad Slider group type will shift elements when it loads. See below for information on how to pre-reserve enough space.
Refreshing ads
Since the option to refresh ads on the spot bases on our cache-busting technology, you can reserve the placement height using the code snippets below.
Groups using that option preserve the height of the highest ad for the placement. While I haven’t been able to measure an impact on CLS, I would suggest you use either only ads with the same height in an automatically rotating group or at least start the rotation with the highest ad.
Sticky and PopUp ads
Even though they don’t shift content, technically, my tests showed that sticky header or footer elements have a slight impact on the CLS score. So does the PopUp when placed at the bottom. Surprisingly, placing a PopUp in the middle of the screen does not influence the score.
There is no measurable effect when the sticky ads load with a delay after the CLS score is calculated. I don’t know how Google will measure this in the future and suggest that you don’t change your ad setup based on this current behavior.
Privacy module
Using the privacy module, especially our TCF integration, increases the CLS score because it has to confirm the user’s consent after the page was loaded.
You would also need to reserve that space in advance, which means that it would stay blank if the user does not give their consent.
How to reduce Cumulative Layout Shift
To fix the layout shift, you need to reserve the space that is later filled with an ad.
In any case, you need to be aware that the reserved space will stay blank if no ad shows up. If you would collapse that space when it stays empty then you would create a new layout shift, which is what we wanted to prevent in the first place.
Using inline CSS to reserve height for placements
You can fix the negative CLS score for ads delivered with placements most conveniently using the Inline CSS option that you can find in the options for each placement. This is the simplest solution we recommend to improve the CLS score of your website. It also works if you use cache busting on these placements.
To reserve a minimal height of 90px, insert the following rule into the Inline CSS field: min-height:90px;. Change 90 to another value if your ads are bigger or smaller.
Placement Inline CSS option to resolve Cumulative Layout Shift issues
Please note that your modifications to the inline CSS will outweigh the CSS rules you define globally. For example, if you have determined a global CSS rule min-height for a specific placement but then use the inline CSS option for that placement, the latter will override your global CSS rule.
We recommend working with min-height instead of height. Because if an ad is a bit bigger than expected, e.g., with dynamic ads like Adsense or embedded iframes, it will not be cut off with min-height in contrast to height, and still, the CLS value is significantly improved.
The pure CSS without brackets or anything else is enough.If you want to set several specifications, put them simply in a row like this: min-height:90px;margin-top:20px;.
Reserve space option
The Reserve space option on the ad edit screen helps with CLS when either the placement delivering the ad, or the ad itself does not use cache-busting. A use case could be a sidebar ad that you embed using the Advanced Ads widget, while the cache busting for ads delivered without placement is disabled.
There are some ad types that provide an option to set the height and width of the ad unit. The “Plain Text and Code”, the “Rich Content”, and the “Ad group” types also allow you to reserve ad space by enabling the appropriate checkbox.
A leaderboard size using the “reserve this space” option.
Using global CSS rules
If you don’t want to use either of the above methods to solve cumulative layout shift problems caused by ads, you can define global CSS rules for them instead. I will show you a few CSS examples to do that.
The CSS code I am proposing here needs to be loaded with the page. You can either add it to your theme’s CSS or in the appropriate Customizer field. See How can I apply custom CSS to my Blog? for further information.
All code examples are targeting the placement wrapper. This is a div element with a class attribute that consists of the prefix set up under Advanced Ads > Settings > ID prefix and the name of the placement in the form of a lowercase slug.
Assuming that your prefix is mysite- and the placement name is “Before Content,” the placement class would be mysite-before-content.
If you are not experienced with CSS, then please ask your frontend developer to implement the changes.
Reserve the height
If all ads in the placement have the same height on all devices then use a CSS rule like this with an example of 90px.
div { overflow: auto; } .shcb-language { border: 0; clip: rect(1px, 1px, 1px, 1px); -webkit-clip-path: inset(50%); clip-path: inset(50%); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; word-wrap: normal; word-break: normal; } .hljs { box-sizing: border-box; } .hljs.shcb-code-table { display: table; width: 100%; } .hljs.shcb-code-table > .shcb-loc { color: inherit; display: table-row; width: 100%; } .hljs.shcb-code-table .shcb-loc > span { display: table-cell; } .wp-block-code code.hljs:not(.shcb-wrap-lines) { white-space: pre; } .wp-block-code code.hljs.shcb-wrap-lines { white-space: pre-wrap; } .hljs.shcb-line-numbers { border-spacing: 0; counter-reset: line; } .hljs.shcb-line-numbers > .shcb-loc { counter-increment: line; } .hljs.shcb-line-numbers .shcb-loc > span { padding-left: 0.75em; } .hljs.shcb-line-numbers .shcb-loc::before { border-right: 1px solid #ddd; content: counter(line); display: table-cell; padding: 0 0.75em; text-align: right; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; white-space: nowrap; width: 1%; } ]]>.mysite-before-content { height: 90px; }
Code language: CSS (css)
If you are not sure about the height and don’t want higher ads to be cut off, use min-height.
.mysite-before-content { min-height: 90px; }
Code language: CSS (css)
Reserve space based on the viewport
Use media queries to reserve a different height depending on the device size.
The example below shows how to reserve a height of 90px on devices wider than 800px and 250px on narrower devices. This works well when your ad setup also delivers different ads based on the “browser width” visitor condition.
.mysite-before-content { height: 250px; } @media screen and (min-width: 800px) { .mysite-before-content { height: 90px; } }
Code language: CSS (css)
Reserve space with relative dimensions
When you are using responsive image ads like leaderboards, then their height would shrink on smaller screens.
Unfortunately, there is no simple solution for this yet. Modern browsers do not yet support the aspect-ratio CSS property, but you can find workarounds here.
Reserve space for blocks that wait for consent
When using the TCF 2.0 integration in Advanced Ads, ad blocks are using a different HTML code that needs another CSS rule. The following example allows you to reserve 250px for all ad blocks that wait for consent.
script[data-tcf="waiting-for-consent"] { margin-top: 250px; /* you can adjust the reserved space here */ display: block; height: 0; overflow: hidden; }
Code language: CSS (css)
To target individual placements, replace the first line with script[data-placement=”PLACEMENT_ID”].
Resources
Starting in 2009, Thomas’ own word game website grew to 40 MM page impressions per month. He then built Advanced Ads to help his colleagues to place ads and test different ad positions and networks tests without any coding skills. Thomas now enjoys improving the product for our more than 150,000 users worldwide.