/ CLS Debugger Fixes / Fix CLS in WordPress

How to Fix CLS in WordPress: Stop Layout Shift From Ads

Cumulative Layout Shift breaks WordPress sites more often than any other Core Web Vital because the platform's open architecture invites layout-shifting injections from themes, plugins, ad networks, cookie banners and lazy-loading optimisers. This guide walks the WordPress-specific audit-and-fix loop: identify the source, apply the fix where it lives (theme, plugin, custom code), and verify against the CLS Debugger output. Related fixes: LCP and INP on the same site usually move together with CLS.

Step 1: Audit the current state

Open PageSpeed Insights at https://pagespeed.web.dev/ and run five representative URLs from your WordPress site: homepage, top-traffic blog post, a category archive page, a contact or about page, and (if applicable) a WooCommerce product page. Note the CLS score under mobile — that's where most WordPress sites fail. A score above 0.25 is poor; under 0.1 is good. Most WordPress sites running default themes with plugins score 0.15–0.40 untreated.

Pair this with our CLS Debugger which records the actual shifting elements in the DOM so you can identify the source rather than guess. The Debugger flags the highest-impact shift first — fixing it usually halves your CLS in one change.

Step 2: Force image dimensions everywhere

Since WordPress 5.5, the core Image block automatically adds width and height attributes to img tags from the media library. But three common WordPress patterns skip this:

Theme template images. Hero banners, featured-image fallbacks, and theme-default placeholders often output <img src="..."> without dimensions. Audit your theme's template files (header.php, single.php, archive.php) and add explicit attributes:

<img src="<?php echo get_template_directory_uri(); ?>/img/hero.jpg"
     width="1200" height="600" alt="..." />

ACF (Advanced Custom Fields) images. When outputting an ACF image field manually, dimensions are often omitted. Use the array return type and output explicitly:

<?php $img = get_field('hero_image'); ?>
<img src="<?php echo esc_url($img['url']); ?>"
     width="<?php echo $img['width']; ?>"
     height="<?php echo $img['height']; ?>"
     alt="<?php echo esc_attr($img['alt']); ?>" />

Page builder content. Elementor, Divi and Beaver Builder sometimes inject inline images without dimensions, particularly in older templates or custom widget configurations. Run a site-wide HTML scan with our HTML Checker to find images missing dimensions, then edit the builder modules.

Step 3: Reserve space for ad slots

Late-loading ads are the single biggest CLS culprit on content WordPress sites. The fix is to reserve the exact slot dimensions before the ad request fires:

<div class="ad-slot" style="min-height:250px;display:block">
  <!-- AdSense / Ezoic / MediaVine code here -->
</div>

For AdSense Auto-ads (which inject ads dynamically without your control), the most reliable mitigation is to switch off Auto-ads and place manual ad units with reserved containers. AdSense Auto-ads on WordPress score CLS poorly almost unavoidably.

For Ezoic and MediaVine, both publishers provide WordPress plugins. Enable the plugin's "preserve slot dimensions" or "CLS-safe mode" option (named differently in each). MediaVine specifically has the Trellis theme which is CLS-optimised; if you're on MediaVine and CLS-burdened, switching themes is the fastest path.

Step 4: Control web font loading

Font-swap CLS happens when a fallback font renders first, then swaps to your web font once it loads, shifting all surrounding text. Three fixes, in order of effectiveness:

1. Use font-display: optional in your @font-face declarations. This tells the browser to use the fallback for 100ms only — if the web font isn't ready, it sticks with the fallback for the whole session. Zero CLS, slight visual inconsistency on slow networks.

@font-face {
  font-family: 'Inter';
  src: url('/fonts/inter.woff2') format('woff2');
  font-display: optional;
}

2. Host Google Fonts locally. Loading from fonts.googleapis.com adds DNS, TLS and CSS request overhead. Use a plugin like OMGF (Optimize My Google Fonts) or download and self-host. Combine with font-display: optional for maximum effect.

3. Match the fallback font metrics. Use size-adjust, ascent-override and descent-override in @font-face so the fallback renders at the same height as your web font:

@font-face {
  font-family: 'Inter-fallback';
  src: local('Arial');
  size-adjust: 107%;
  ascent-override: 90%;
  descent-override: 22%;
}

Step 5: Audit plugin-injected content

This is the most painful step because the culprit is usually a plugin you "need." The systematic approach:

On a staging copy of your site, disable plugins one by one and re-measure CLS after each. Plugins that commonly cause CLS in WordPress:

Step 6: Re-test and verify

After each batch of fixes, re-run PageSpeed Insights. Lab data updates immediately. Field data (the 28-day rolling CrUX dataset that Google actually uses for Core Web Vitals ranking signals) takes 4-6 weeks to fully reflect changes. Track both: lab numbers daily during the fix programme, then watch field data trend over the following month.

Verify with a real Chrome DevTools Performance recording on a throttled "Fast 3G" connection — that's closer to real mobile conditions than the default desktop. Look for shifts in the Layout Shift Regions visualisation.

💡 Add CLS to your weekly monitoring. Plugin updates routinely regress CLS — a "minor" update to your ad plugin or cookie banner can wipe out months of work overnight.

Frequently Asked Questions

Why is CLS worse on mobile than desktop in WordPress?
Mobile viewports are narrower, so reflows have bigger relative impact. Ads loading 320px wide on a 375px viewport push content significantly. Mobile also tends to load web fonts later because connections are slower, amplifying font-swap shift. WordPress themes are often desktop-first in their CSS, so mobile breakpoints inherit assumptions that don't hold under real conditions.
Does Gutenberg fix CLS automatically?
Partially. Gutenberg image blocks output width and height attributes by default since WordPress 5.5, which prevents the most common cause of CLS. But Gutenberg does NOT solve CLS from late-loading ads, font-swap shift, lazy-loaded embeds (YouTube, Twitter), or injected widgets from third-party plugins. You still need the full audit.
Which WordPress plugins commonly cause CLS?
Cookie consent banners that load late and push content down, sticky header plugins that activate on scroll, related-posts plugins inserting content above the fold, ad management plugins without reserved-space containers, and chat widgets (Tidio, Intercom) that grow on init. Audit by selectively disabling each on a staging copy.
Will switching theme fix CLS?
Only if the new theme follows CLS best practices and you migrate plugins thoughtfully. Lightweight themes (GeneratePress, Astra, Blocksy) tend to score better out of the box. But CLS is more about loading sequence than theme weight — a heavy theme with correct image dimensions and reserved ad slots can outperform a lightweight one with injected widgets.
How long does it take WordPress CLS fixes to show up in PageSpeed Insights?
Lab data updates immediately after a fix. Field data (the 28-day real-user CrUX dataset) takes 4-6 weeks to fully reflect changes because it's a rolling average. Track lab numbers daily during fixes, then watch field data trend down over the following month.

🔎 Audit your CLS first

Identify the exact elements causing layout shift with our CLS Debugger.

Run CLS Debugger →
Related Guides: CLS Debugger Guide  ·  All CLS Fixes  ·  Page Speed Guide  ·  Core Web Vitals Guide
💬 Got a problem?