Cumulative Layout Shift (CLS) is the most annoying Core Web Vital, for you and your visitors. It measures how much a page’s content jumps around while loading: the text that suddenly moves down when an image appears, the button that shifts right under your thumb a split second before you tap it.
Google wants CLS below 0.1. The good news: unlike some speed metrics, CLS is almost never a hosting problem. It is caused by a small set of predictable mistakes — the six usual suspects below — and each one has a straightforward fix.
The short answer: most WordPress CLS problems come from images without reserved dimensions, web fonts that swap late, cookie banners and popups injected over content, and ads inserted into reserved space. Fix these and CLS typically drops into the green.
What CLS Actually Measures (In Plain English)
CLS adds up every unexpected layout shift during a page’s life, weighted by how much of the screen moved. It does not measure how long your page takes to load — it measures how stable it feels. A page can load slowly but score a perfect CLS if nothing moves, and a fast page can fail if content keeps jumping.
The most common real-world symptom: a visitor starts reading, an ad or image loads late, everything shifts down, and they lose their place, or tap the wrong button. Google penalizes this because users hate it.
Suspect #1: Images Without Reserved Dimensions
This is the #1 cause of CLS on WordPress sites. When the browser does not know an image’s size in advance, it renders the text first, then pushes everything down when the image finally loads.
The fix: make sure every image has width and height attributes (WordPress adds these automatically when you insert images through the media library; problems start when images are added via page builders, custom HTML, or lazy-load plugins that strip attributes). Modern CSS then preserves the aspect ratio automatically with aspect-ratio behavior, so responsive images keep their space at every screen size.
Checklist for this suspect:
– In your page builder, avoid “auto” sized image widgets that omit dimensions
– If you write custom HTML for images, always include width and height
– If you lazy-load images, use a proper lazy-loading method (native loading="lazy" or a reputable plugin), because lazy loading images properly should never remove the reserved space
– Hero images should be preloaded, not lazy-loaded (lazy-loading the biggest image on screen delays it and can cause a shift)
Suspect #2: Web Fonts That Swap Late
Custom fonts are the second classic CLS culprit. The browser renders text in a fallback font, then the web font arrives and every line re-wraps — shifting headings, buttons and entire sections.
The fix, three layers, easiest first:
- Use
font-display: swapin your font CSS. This is the minimum. It tells the browser to show text immediately in a fallback font rather than hiding it (invisible text is arguably worse than a shift, but swap at least keeps things readable). - Preload your most important font files. Add
<link rel="preload">for the 1–2 font files used in above-the-fold headings. This makes the real font arrive before first paint, eliminating the swap entirely for the visible area. - Match your fallback font’s metrics. Advanced themes let you define
size-adjust,ascent-overrideanddescent-overridedescriptors so the fallback font occupies nearly the same space as the web font. When the swap happens, almost nothing moves.
The nuclear option: if your design allows it, use system fonts for body text. Zero font files, zero font-induced shift, and on most devices they look perfectly fine.
Suspect #3: Cookie Banners and Popups Injected Over Content
Consent banners are legally necessary in many regions. But the way most plugins implement them causes CLS. The banner’s HTML is injected by JavaScript after the page renders, pushing content down or reflowing the layout.
The fix:
– Choose a consent plugin that overlays the banner (fixed position at the bottom) instead of pushing page content down. A fixed overlay does not cause layout shift because it does not move other elements.
– Reserve the banner’s space in advance if it must sit in the document flow. But overlay is almost always the better answer.
– Load the consent script efficiently, but do not delay it so aggressively that the banner pops in seconds after the user started reading. A banner that appears late over content is a minor annoyance; one that shifts content is a CLS failure.
Suspect #4: Ads Inserted Without Reserved Space
If you run display ads (AdSense, Mediavine, AdsKeeper or similar), late-loading ad units are a notorious CLS source. The ad slot collapses to zero height, content flows up, then the ad loads and shoves everything down.
The fix:
– Reserve a fixed-size container for every ad slot. If your ad unit is 300×250, wrap it in a div with min-height: 250px (or the appropriate size for each breakpoint). The space is held whether or not the ad fills.
– For responsive ad units, reserve space for the largest size you expect at each breakpoint. An empty reserved box is invisible to visitors but priceless for CLS.
– Never let ad scripts inject new slots into the middle of article content after load. Define all slots in the initial HTML.
– Sticky/floating ad units (fixed position) do not cause layout shift. Consider them for mobile, where CLS failures are most common.
Suspect #5: Embeds and Iframes (Videos, Maps, Social Posts)
YouTube embeds, Google Maps, Twitter/X embeds and similar iframes behave exactly like images without dimensions: the browser does not know their size until they load, so content below them jumps.
The fix:
– Wrap every embed in a container with a fixed aspect ratio (16:9 for video is the classic). The well-known CSS pattern is a wrapper with position: relative; padding-bottom: 56.25% and the iframe absolutely positioned inside, or the modern aspect-ratio: 16/9 property.
– For “click to play” facade embeds (which replace heavy YouTube iframes with a lightweight preview image), make sure the preview image has the same dimensions as the final player so the swap is seamless.
– Social media embeds that resize after loading are the worst offenders. Where possible, use a static screenshot linked to the post instead of a live embed.
Suspect #6: Dynamic Content Injected Above Existing Content
Anything that inserts content above what the visitor is already reading causes a shift: “related posts” widgets loaded by AJAX, announcement bars that slide in, font-size adjustments, or AJAX-loaded comments appearing at the top of the comment section.
The fix:
– Reserve space (min-height) for any widget that loads asynchronously.
– Announcement bars should either be in the initial HTML or slide in as fixed overlays.
– If you A/B test headlines or layouts, use tools that apply variations before first paint, not after.
How to Find Your Own CLS Culprits
Do not guess. Measure:
- PageSpeed Insights shows your CLS score per page and flags the specific elements that shifted most (“Avoid large layout shifts” lists the offending elements).
- Search Console’s Core Web Vitals report shows which URL groups fail CLS across your whole site. Fix the template, fix every page using it.
- Chrome DevTools: open the Performance panel, record a page load, and look for “Layout Shift” events in the timeline. You can see exactly which element moved and what caused it.
Fix the template-level issues first (header, ads, fonts affect every page), then spot-check your most important pages individually.
The CLS Fix Order That Works
If you want a prioritized battle plan:
- Add missing image dimensions (biggest single win on most blogs)
- Reserve space for ad slots and embeds
- Preload critical fonts + use
font-display: swap - Switch the cookie banner to fixed overlay mode
- Reserve space for AJAX-loaded widgets
- Re-test in PageSpeed Insights and Search Console
Most WordPress sites that work through this list in order see CLS drop below 0.1 without touching hosting, themes or caching plugins. CLS is a markup and CSS problem, which means it is entirely within your control. Our 20-step WordPress performance checklist covers the other two Core Web Vitals if you want to finish the job.
Frequently Asked Questions
What is a good CLS score for WordPress?
Google’s threshold is 0.1 or below for “Good.” Between 0.1 and 0.25 “Needs Improvement,” above 0.25 “Poor.” Aim for below 0.1 on both mobile and desktop — mobile is usually the harder of the two because of smaller viewports and slower networks.
Can a caching plugin fix CLS?
No — caching plugins speed up delivery but do not change what the browser renders or in what order. CLS is caused by HTML structure, CSS and late-loading resources. No cache setting adds image dimensions or reserves ad space. Fix the markup first.
Why is my CLS fine on desktop but poor on mobile?
Mobile viewports are smaller, so the same shift covers a larger fraction of the screen (CLS is viewport-relative). Mobile networks are also slower, so late-loading resources arrive later and shift more visibly. Always optimize for the mobile score — it is the one Google uses for ranking.
Do lazy-loaded images hurt CLS?
Only if implemented badly. Proper lazy loading (native loading="lazy" or a quality plugin) preserves the image’s reserved space, so no shift occurs. Problems come from lazy-load implementations that strip width/height attributes or from lazy-loading above-the-fold images, which delays content the visitor needed immediately.
How long after fixing CLS will Search Console update?
Search Console’s Core Web Vitals data is based on 28 days of real-user (field) data, so improvements appear gradually as new visitor data replaces old. Lab tools like PageSpeed Insights reflect your fixes immediately — use those to verify, and let Search Console catch up on its own.

