How To Reduce Cumulative Layout Shift To “0” in WordPress

Want to improve cumulative layout shift in WordPress?

Cumulative layout shift (CLS) means elements on your website are shifting while the page is loading. To see layout shifts on your site, use Google’s Layout Shift Debugger. It creates a GIF highlighting the layout shifts, which is necessary since they often happen too fast to be noticed.

Google recommends a CLS score of 0.1 or less (anything over .25 is poor). As of writing this, cumulative layout shift is weighted at 15% of Lighthouse scores and can often be easy to fix.

In WordPress, cumulative layout shift is often caused by asynchronous or critical CSS settings in cache plugin settings, FOIT issues with fonts, and not specifying dimensions for your content.

What Is A Good CLS Score?

Under .1Good


1. Learn Which Elements Are Shifting

Cumulative Layout Shift Debugger – creates a GIF showing you all mobile + desktop layout shifts in a GIF. Built by a Chrome engineer and the main tool I recommend to find CLS issues. If most of the text on the page is highlighted, chances are your fonts are causing the layout shifts.

Cumulative layout shift debugger

PageSpeed Insights – the “avoid large layout shift” report in your Diagnostics section shows you which individual elements have the highest CLS contribution, as well as a picture of them.

Avoid large layout shifts wordpress

Layout Shift Regions In Chrome Dev Tools – view layout shifts highlighted in blue while browsing your website in real-time. Here are instructions for enabling layout shift regions:

  • Open Chrome Dev Tools.
  • Open the Command Menu.
  • Start typing “Rendering.”
  • Run the Show Rendering command.
  • Enable the Layout Shift Regions checkbox.
  • As you interact with a page, layout shifts are highlighted blue.

Layout shifts in chrome dev tools


Another trick is to open Chrome Dev Tools and throttle your bandwidth so your website loads extremely slow. Use a slow 3G connection or set an even slower custom connection (e.g. 100 kbps). This gives you enough time to see which elements on your site are causing layout shifts.

Chrome dev tools cls


2. Disable Asynchronous CSS

Most cache plugins have a setting to load CSS asynchronously (optimize CSS delivery in WP Rocket or load CSS asynchronously in LiteSpeed Cache).

This can cause FOUC (flash of unstyled content) where the page’s contents are loaded before the CSS. Not only does this look bad when your site is loading, but it can also cause layout shifts.

Fouc flash of unstyled content
Using asynchronous CSS without critical CSS can cause FOUC (flash of unstyled content)

Disabling optimize CSS delivery or load CSS asynchronously in your cache plugin should improve your cumulative layout shift score. There are multiple reports of this in Facebook Groups and this was also brought to my attention by Richie and Vishal in this post’s comments. Many people remove unused CSS in WP Rocket’s settings, then disable optimize CSS delivery.

Disable optimize css delivery in wp rocket
Try disabling “optimize CSS delivery” if using WP Rocket
Disable load css asynchronously litespeed
Try disabling “load CSS asynchronously” if using LiteSpeed


3. Use Critical CSS

If you want to load CSS asynchronously without FOUC, you’ll want to use critical CSS. This only loads the CSS needed to display above-the-fold content, then the rest of the CSS is loaded later.

WP Rocket Instructions

  • Enable optimize CSS delivery in WP Rocket.
  • Search for “rocket-critical-css” in the source code to make sure it’s working.
  • If it’s not working, regenerate critical CSS in WP Rocket and your page builder.
  • Run your site through a critical path CSS generator.
  • Copy the critical path CSS code.
  • Paste the code into the “fallback critical CSS” field.
  • If needed, disable optimize CSS delivery on individual pages/posts.
  • If necessary, exclude files from CSS delivery using WP Rocket’s helper plugin.

Critical path css generator

Wp rocket fallback critical css
Try setting a fallback critical CSS if using WP Rocket

LiteSpeed Cache Instructions

  • Enable load CSS asynchronously in LiteSpeed Cache.
  • Turn generate critical CSS to On.
  • Turn generate critical CSS in background to On.

LiteSpeed says:

“When (generate critical CSS in background) is enabled, the first visitor to request the page doesn’t have to wait for the Critical CSS to be generated. Instead of waiting for the remote CCSS server to calculate and return the Critical CSS, LSCache instead adds the page to a cron-based queue to be calculated later in the background. In the meantime, the page continues to load asynchronously for the visitor without waiting.

The only drawback to this approach is that the first visitor is likely to get the FOUC. You need to decide which is worse: a quick flash of unformatted content? or having to wait a few seconds for the Critical CSS to be generated before anything on the page loads at all? If it were me, I’d take the FOUC.”

Asynchronous css settings litespeed cache
Try generating critical CSS if using LiteSpeed Cache


4. Host Fonts Locally And Preload Them

Other than preconnect, third-party fonts don’t let you optimize them much.

The first step to optimizing fonts is to host them locally. Instead of pulling them from or, hosting them locally ( for me) is much faster. You can use tools like the OMGF plugin or Transfonter to host fonts locally.

Host fonts locally

Once fonts are hosted locally, preload them. PageSpeed Insights may recommend font files to preload under preload key requests. Otherwise, find your font files in GTmetrix Waterfall in the “fonts” section. Copy their URLs and preload them (this can be done manually, in WP Rocket, Perfmatters, and other speed plugins). If there’s an option to enable crossorigin for fonts, use it.

Preload fonts wp rocket

Preload fonts


5. Add Font-Display: Swap To Fonts

Adding font-display:swap to your font’s CSS ensures text remains visible during webfont load.

Otherwise, fonts can shift while the page is loading which causes layout shifts due to FOIT (flash of invisible text). If you’re using Google Fonts, you can just use the Swap Google Fonts Display plugin. Otherwise, you’ll need to find the font’s CSS file, then add font-display: swap.

Foit - flash of invisible text

Step 1: View your “ensure text remains visible during webfont load” report in PSI.

Ensure text remains visible during webfont load

Step 2: Install the String Locator plugin and use it to search for the problematic font (i.e. slick.woff) and find the CSS file where it’s loading. Edit the stylesheet and search for the font.

String locator

Step 3: Add font-display: swap to the font’s CSS. How you do this can depend on your fonts, theme, and plugins. But I listed some of the most common solutions below. You might also discover that instead of “swap” the font is using something else like auto, block, fallback, etc.

Without Font-Display Swap:[email protected]

With Font-Display Swap:[email protected]&display=swap

Without Font-Display Swap:

@font-face {
font-family: 'slick';
font-style: normal;
font-weight: 300;
src: local(''),
url('../fonts/slick.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */

With Font-Display Swap:

@font-face {
font-family: 'slick';
font-display: swap;
font-style: normal;
font-weight: 300;
src: local(''),
url('../fonts/slick.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */


6. Specify Image Dimensions

Specifying image dimensions means you need to add a width/height attribute to the image’s HTML. Or you can do it by enabling add missing image dimensions in WP Rocket’s Media tab.

<img src="example.png" width="680" height="680" />

If images don’t have specified dimensions, you’ll see this error:

Image elements do not have explicit width and height


7. Specify Video And Iframe Dimensions

Similar to images, videos and iframes should also have a width and height specified in the embed code. It’s also  important to make sure embedded videos and iframes are responsive.

<iframe src="" width="680"
height="340" ></iframe>


8. Use CSS Transform Property In Animations

Many WordPress sites use animations, but they can cause layout shifts.

Google recommends using the CSS transform property to use animations without causing layout shifts. Instead of changing width + height attributes, use transform: scale(). To move elements around, use transform: translate() instead of changing the top, right, bottom, or left property. In the image below, I used the Happy Addons for Elementor plugin for CSS Transform.

Css transform

I recommend testing a page with and without animations to see the difference in your cumulative layout shift score. If you really think animations are worth it, keep them. But it’s been reported many times in Facebook Groups that animations can slow down WordPress.

This has been reported by Google.

Cumulative layout shift - wordpress animations


9. Reserve Space For Advertisements

Ads can also cause layout shifts, and it’s very noticeable if they load above the fold.

If you don’t reserve space for ads, they can shift other content on the page when the ads are eventually loaded. By placing the ad code inside a div that specifies the ad’s dimensions, space will be reserved for your ads so they don’t cause layout shifts for non-ad content on the page.

Google recommends reserving space for the largest size advertisements are configured to serve. They also recommend reserving space for the size most likely to be served (found in historical fill data from Google Ad Manager reports).

Google has quite a few examples of specifying ad dimensions in CSS and JavaScript.

<div class="ad" style="min-width: 300px; min-height: 250px;"></div>


10. Serve Dynamic Content Properly

Dynamic content is clearly listed as a common offender for cumulative layout shift.

If you must use dynamic content, reserve space for it using placeholders (specify a width and height). This ensures other elements on your page won’t shift when dynamic content is loaded.

Dynamic Content Examples:

  • Advertisements
  • Pops
  • Banners
  • Forms
  • GDPR notices

If you’re serving popups, Graham Ritchie on Stack Overflow says:

“You can fix this by adding position:fixed to the popup. This will take it out of the document flow and not cause a layout shift. (assuming it is more like a toast that covers the bottom of the screen rather than a dialog box style popup). You need to ensure that this style is applied inline within the HTML before the popup to stop it moving around once it receives styling.”

“Alternatively you can make the popup a bar at the top of the page (doesn’t have to be position: fixed as it can push the content down), at which point it will render correctly (assuming you inline your CSS).”


11. Use A Lightweight GDPR Plugin

Believe it or not, your GDPR plugin can also contribute to cumulative layout shift.

This happens when certain elements stack on top of each other. I personally use Cookie Notice & Compliance for GDPR / CCPA for my GDPR plugin which causes minimal layout shifts (if any).



12. Hard Code Your Menu And Header

If your menu and header cause cumulative layout shifts, consider hard coding them.

Regardless of whether they increase CLS, hard coding them is more lightweight than using page builders for these areas (as well as your footer). Elementor and Divi specifically add extra CSS and JavaScript to your site and hard coding these areas can make significant improvements not only to cumulative layout shift, but other PageSpeed Insights items related to CSS + JavaScript. I hired WP Johnny for his page builder removal services and this is exactly what he started with.


13. Set Global Font To Mulish In Oxygen Builder

If you’re using Oxygen Builder, there have been reports of global font settings causing CLS issues. The current solution seems to be to open stylesheets and set the global font to Mulish.

body { font-family: 'Mulish', sans-serif; }


Retest Your Cumulative Layout Shift Score

Retest your site in PageSpeed Insights, GTmetrix, or ideally Lighthouse. Hopefully your cumulative layout shift is minimal or zero. Remember, you need a CLS of under .1 to be green.

Cumulative layout shift wordpress - gtmetrix report

See Also: Optimize WordPress For Core Web Vitals


Frequently Asked Questions

How do I reduce cumulative layout shift in WordPress?

Disable asynchronous CSS in your cache plugin, use critical CSS, and host fonts locally while preloading them to fix CLS issues in WordPress. You should also specify content dimensions (images, videos, iframes, ads), and use CSS transform when using animations.

Which WordPress plugins fix layout shifts?

Swap Google Fonts Display, OMGF, WP Rocket, and LiteSpeed Cache are a few WordPress plugins that can reduce cumulative layout shift when the settings are configured optimally.

How do I reduce cumulative layout shift in WP Rocket?

Disable Optimize CSS Delivery or try enabling it with a fallback critical CSS. Also make sure Add Missing Image Dimensions is enabled.

Drop me a comment if you have any questions! If you need help, please leave a link to your GTmetrix report and not your website or it will be marked as spam. I would appreciate it :)


About Tom Dupuis

Tom Dupuis writes WordPress speed and SEO tutorials out of his apartment in Denver, Colorado. In his spare time, he plays Rocket League and watches murder documentaries. Read his bio to learn 50 random and disturbing things about him.

16 thoughts on “How To Reduce Cumulative Layout Shift To “0” in WordPress

  1. I managed to get my CLS score down to 0.00. But there is an element I really like for my users that brings it back up to 0.01. I read what you said about 0.01 or less being fine. But if the shifting element I want is not really vital to my website, should I remove to have a 0.00?

    1. If it was my website I would only because I blog about speed. Since yours isn’t, I would just keep the element if you really like it. .01 is so small I doubt it’s going to make or break anything.

  2. OMG!!! Thanks 1000 times Tom, I have a post with 10.000 words, 10 videos and countless images. It was already very optimised, but still got a 35 on mobile in google page insight… But with your post on divi and this post, I optimised again, and I can’t even believe it, can’t understand how it is possible for such a big post using divi. But I now get a 98 on mobile, crazy!! (Especially to disabled “optimise CSS delivery” in WP rocket reduced my CLS from 0.610 to 0.004! And in the last version of WP rocket, there is a new option to remove unused CSS, made a big difference too.)

    1. That’s awesome Antoine. Yeah, a lot of people are using the removed unused CSS option in WP Rocket and disabling optimize CSS delivery. Seems to be a popular setup at the moment. Glad the tutorials were so useful and you got such good results :)

  3. Tom, terrific article. Just so you know, I unchecked the Optimize CSS Delivery in WP Rocket (+ added the fallback CSS from PurifyCSS) and my core web vitals turned green all at once! They were OKish before but the CLS dropped to 0.01, which is unreal! Thank so much for the tips!

    1. Just a follow up to my previous comment. By unchecking the Optimize CSS Delivery in WP Rocket you will NOT preload a bunch of JS / CSS files, which ultimately will result in a lower score on Page Speed Insights. The compromise I found was checking Optimize CSS Delivery in WP Rocket without providing any fallback CSS. Hope it helps

  4. As ever, thanks for a great guide, Tom. Although I had a pretty quick loading time for my Home page I was getting warnings about CLS. It took a while to track down the cause but your guide pointed me in the right direction. For me, it was having the ‘Load CSS Asynchronously’ option selected in Litespeed Cache – once I removed that the CLS was down to 0.

  5. I got an avg CLS of 0.68 in my search console. I check for the moving components through chrome dev tool and its turn out my breadcrumbs and fonts. I think, you should try to disable optimize CSS delivery in WP rocket first. It may or may not work for you, but now my CLS score is 0.12 for mobile and 0.007 for desktop (according to the page speed insights).
    By the way, thanks for the help buddy!!! 

Leave a Reply

Your email address will not be published.