How to Fix CLS Caused by Ads, Before the Ads Arrive
There is a specific kind of mistake that only becomes visible after you monetise: the ad slot was added to a template that had no space reserved for it, the page reflowed on every load, and the metric that measures this has been degrading for weeks before anyone looks.
The reason it is worth reading about now rather than later is that the fix is architectural. Reserving space for an ad is trivial in a template and awkward to retrofit across a site. And the underlying metric is more subtle than the way it is usually summarised.
Getting the metric right first
Core Web Vitals are currently LCP, INP, and CLS — all assessed at the 75th percentile, segmented separately for mobile and desktop:
| Metric | Good | Needs improvement | Poor |
|---|---|---|---|
| LCP | ≤ 2.5 s | 2.5–4.0 s | > 4.0 s |
| INP | ≤ 200 ms | 200–500 ms | > 500 ms |
| CLS | ≤ 0.1 | 0.1–0.25 | > 0.25 |
If you have internal documents that still list FID as the interactivity metric, they are out of date. INP replaced FID, FID support was formally deprecated, and Google set a hard transition deadline of 9 September 2024 for CrUX and PageSpeed Insights API consumers. Stating FID as current is wrong, and it is a cheap way to date your advice.
Note also that CLS has no unit. It is not milliseconds and it is not a percentage. A score of 0.1 is the threshold, and it accumulates, which is what makes the next section matter.
How CLS is actually calculated
This is the part most explanations get wrong. CLS is not the sum of every layout shift on the page.
It is the largest session window. Google’s definition: a burst of layout shifts “with less than 1-second in between each shift and a maximum of 5 seconds for the total window duration.” The score for the page is the session window with the maximum cumulative score of all layout shifts within it.
Two consequences that change how you debug:
One bad moment is the whole story. A cluster of shifts inside two seconds determines your score, regardless of how clean the rest of the page is. You do not need to fix every shift; you need to fix the worst burst.
Slow pages are not automatically punished. The 5-second cap exists partly so that a page which keeps shifting for thirty seconds does not accumulate an unbounded score. Live-updating content is not as catastrophic as it looks.
There is also one documented exclusion: layout shifts within 500 ms of a user interaction are excluded, because the user caused them and the resulting movement is expected. Shifts that happen on their own, after load, all count.
Why ads are the worst offender
Google says it directly: “Ads are one of the biggest contributors to layout shift on the web,” and explains the mechanism — “ad networks and publishers often support dynamic ad sizes.” The creative that wins the auction is not known at page-parse time, and it may be any of several sizes.
So the sequence is: HTML renders without the ad, the ad auction completes a few hundred milliseconds later, a slot of unknown height is inserted, and everything below it moves. Large text blocks read as deliberate; images and paragraphs shoved downwards read as broken.
This is worse than a missing image, because a missing image has a known size that you simply failed to declare. An ad’s size is decided by an auction you are not part of.
Reserve the space, and never give it back
The recommended fix is space reservation, and there is one sentence in Google’s guidance that people skip past:
“Reclaiming reserved space can cause as much CLS as inserting content.”
If you reserve a slot and then collapse it when no ad is sold, you have moved everything on the page a second time. Google’s explicit advice is to show a placeholder rather than collapsing the slot. The empty space is the price.
That is the design decision, and it is a real one: you are choosing to show an empty box to some readers in order to keep the page stable for all of them.
The techniques Google actually documents
| Technique | Use when | Notes |
|---|---|---|
min-height on the slot | The ad has a predictable minimum size | Simplest and most robust |
aspect-ratio | The slot is adaptive but has a known shape | Google’s recommendation for adaptive content |
| Media queries | Slot size varies by breakpoint | Combine with the above |
| Placeholder content | No ad was returned | Never collapse to zero height |
A reserved slot that never fills is not a wasted slot. It is a slot doing its job, which is to hold a fixed amount of space so that nothing else has to move.
What is not in the official guidance
contain-intrinsic-size is a genuinely useful CSS property for this problem, and you will find it recommended widely. It is not part of Google’s documented ad-CLS guidance — Google’s page names min-height and aspect-ratio. It may well work for you, but treat it as a technique you are testing rather than one the vendor endorses.
The other thing worth flagging: no ad network publishes slot dimension specifications for this purpose. I checked. The publisher documentation from the major networks covers formats and revenue, not layout stability. There are no official recommended slot heights, which means every “ideal ad slot size” figure you read is somebody’s inference.
The font shift that gets blamed on everything else
One more contributor, and it is easy to misattribute. Every font-display value except optional can cause layout shift on swap — including swap, which is the one most performance guides recommend by default. Google’s own wording is that auto, block, swap, and fallback “can all cause layout shift.”
Controls that work: font-display: optional (which Google says ensures no swap-related shift, at the cost of possibly never showing the web font), or swap combined with early delivery plus size-adjust and the metric-override descriptors to shrink the difference between the fallback and the web font. The static site version of this is simpler — use system fonts, ship no web font, and the problem does not exist.
The number nobody will give you
Here is the trade-off, stated plainly: bigger ad units generally earn more, and bigger ad units shift layout more. Reserved space costs you nothing in revenue but occupies attention. There is no published guidance that resolves this, because it depends on your traffic, your layout, and your tolerance for empty boxes.
So you will have to decide it yourself, which means measuring it yourself: load the page with a cleared cache, watch the reserved slot, and confirm nothing below it moves when the creative arrives. Then check that the placeholder case — no ad sold — moves nothing either. The second case is the one people forget to test, and it is the one that produces the worse score.
When to accept the shift
If a slot sits below the fold and nothing beneath it moves, the shift it causes may not reach your worst session window at all, because the 5-second cap and the largest-burst rule mean a late, isolated shift is cheap. Measure before you optimise, and do not trade a good user experience for a metric nobody is failing.
Written by TestedHost. Every recommendation on this site comes from running the setup described, on a live deployment — not from a vendor spec sheet. Spotted something out of date? Tell us.