Skip to content
What To Fix First

Render-blocking resources from WordPress plugins

Render-blocking resources on a WordPress site are almost always plugin and theme stylesheets printed in the head, plus jQuery and plugin scripts printed without defer. Find them per page with the plugin checker or Query Monitor, then either dequeue the ones the page does not use or defer and inline the rest with a settings change in your optimisation plugin.

By , who built this checker and writes the guides. Published How the tool ranks fixes

Why plugins block the paint

The render-blocking guide explains the mechanism: a stylesheet in the head, or a script without defer, stops the browser painting anything until the file has arrived and, for scripts, run. On WordPress the head is where plugins put things by default. wp_enqueue_style() prints a <link> in the head; wp_enqueue_script() prints a plain <script> in the head unless the plugin author asked for the footer or a defer strategy, which many have not. Fifteen active plugins is fifteen stylesheets before the first pixel.

Run the plugin speed test on the page: it groups every file by the plugin that owns it, shows the weight, and marks which files are render-blocking — in the head, without defer or async. That is your list.

Step 1: decide, per file, which fix applies

  • The page does not use the plugin at all. Do not load the file. That is the dequeue fix, covered in its own guide, and it is the largest win because the bytes disappear rather than move.
  • The page uses it, but not for the first view. Defer the script; load the stylesheet asynchronously. Comment forms, sliders below the fold, lightboxes, share buttons.
  • The page needs it to paint. Inline the small part it needs (critical CSS) and load the rest asynchronously. The theme stylesheet, layout CSS, the hero’s styles.

Step 2: the settings, plugin by plugin

WP Rocket

  • File Optimization → CSS Files → Optimize CSS delivery: choose Remove Unused CSS. It generates a per-page stylesheet and inlines it; fall back to Load CSS asynchronously on any page it breaks.
  • File Optimization → JavaScript Files → Load JavaScript deferred, and Delay JavaScript execution for third-party tags and anything not needed until interaction. Add handles to the exclusion box when an inline script complains.
  • Leave Minify and Combine off on HTTP/2 hosts; combining creates one large blocking file.

LiteSpeed Cache (LiteSpeed servers)

  • Page Optimization → CSS Settings → Generate UCSS on, Load CSS Asynchronously on, Generate Critical CSS on.
  • Page Optimization → JS Settings → Load JS Deferred: Deferred, or Delayed for third-party scripts.
  • Tuning → exclusions for the handles that break.

Perfmatters

  • Assets → JavaScript → Defer JavaScript (include jQuery only if nothing inline needs it) and Delay JavaScript with a list of third-party scripts.
  • Assets → CSS → Remove Unused CSS, with the stylesheet handles to exclude.
  • Script Manager: per-page on/off for every handle, which is the dequeue guide without the code.

Autoptimize (free)

  • JS, CSS & HTML → Optimize JavaScript code, and leave Aggregate JS-files off on HTTP/2; the defer is applied to the individual files.
  • CSS → Inline and defer CSS with critical CSS from the built-in or the Critical CSS power-up.

Elementor, Divi and other builders

  • Elementor → Settings → Features: Improved Asset Loading, Improved CSS Loading, Optimized DOM Output. Settings → Advanced: disable the Font Awesome and eicons libraries if no widget uses them.
  • Divi → Theme Options → Performance: Dynamic CSS, Critical CSS, Defer jQuery, Disable WordPress emojis.
  • Builders still ship a fixed baseline per page; the settings shrink it, they do not remove it.

Step 3: the files WordPress itself blocks with

Not every render-blocking file belongs to a plugin. Four come from core and can be dequeued when unneeded, in a must-use plugin:

<?php
add_action( 'wp_enqueue_scripts', function () {
    // Block editor styles on a site that renders no blocks on the front end.
    wp_dequeue_style( 'wp-block-library' );
    wp_dequeue_style( 'wp-block-library-theme' );
    wp_dequeue_style( 'classic-theme-styles' );
    // Dashicons for logged-out visitors (admin bar only needs it when logged in).
    if ( ! is_user_logged_in() ) wp_dequeue_style( 'dashicons' );
    // Global styles inlined by the theme.json system — only if the theme does not need them.
    wp_dequeue_style( 'global-styles' );
}, 100 );

// Emoji detection script and its styles.
remove_action( 'wp_head', 'print_emoji_detection_script', 7 );
remove_action( 'wp_print_styles', 'print_emoji_styles' );

// jQuery Migrate, when no plugin needs deprecated jQuery.
add_action( 'wp_default_scripts', function ( $scripts ) {
    if ( ! is_admin() && isset( $scripts->registered['jquery'] ) ) {
        $scripts->registered['jquery']->deps = array_diff( $scripts->registered['jquery']->deps, [ 'jquery-migrate' ] );
    }
} );

Test each line on a page that uses blocks, one that uses the theme’s styles, and one with a form. If something loses its styling, that page needed the file: restore it with a conditional.

Step 4: defer what must stay, by hand

If you would rather not add an optimisation plugin, WordPress 6.3 and later accept a loading strategy per script, and a filter can apply it to everything but jQuery:

add_filter( 'script_loader_tag', function ( $tag, $handle ) {
    if ( in_array( $handle, [ 'jquery-core', 'jquery-migrate' ], true ) ) return $tag;
    if ( str_contains( $tag, ' defer' ) || str_contains( $tag, ' async' ) ) return $tag;
    return str_replace( ' src=', ' defer src=', $tag );
}, 10, 2 );

For stylesheets, the equivalent is loading non-critical ones with media="print" onload="this.media='all'", which the async-CSS options above do for you.

The order that works

  1. Run the plugin test on three different pages; note the render-blocking files.
  2. Dequeue the ones each page does not use.
  3. Turn on unused-CSS removal (or async CSS with critical CSS) in one optimisation plugin.
  4. Defer all JavaScript except jQuery core; delay third-party tags.
  5. Dequeue the core files above where unneeded.
  6. Self-host fonts: the Google Fonts guide.

Every setting above is available in a free plugin or in the code shown, and the dequeue conditionals live in a must-use plugin you control. When the site has dozens of plugins and no developer, a script manager with per-page on/off, defer and delay switches for every handle saves the afternoon. For that we use Perfmatters. That is an affiliate link: we earn a commission if you sign up, at no extra cost to you.

Check it worked

Re-run the plugin speed test: the render-blocking count should drop to the theme stylesheet and little else. Then the speed test: the render phase on the LCP timeline is where the recovered time appears.

Common questions

Which plugins are the usual render-blocking offenders?
Contact Form 7 (a stylesheet on every page), WooCommerce's blocks stylesheet, Elementor and Divi frontend CSS plus their icon fonts, Font Awesome from any plugin that bundles it, Slider Revolution, Gravity Forms, Table Press, and jQuery plus jQuery Migrate from WordPress itself. The plugin speed test lists yours by weight and marks which are in the head.
Is 'render-blocking' the same as 'unused'?
No. A file is render-blocking because of where and how it is loaded — a stylesheet in the head, a script without defer. It is unused when the page never needs it. The fix for a used file is to defer it or inline the critical part; the fix for an unused one is to not load it at all. Many plugin files are both, which is why the two guides link each other.
Will deferring JavaScript break my site?
Sometimes, for one reason: an inline script that expects a deferred file to have run already. The symptom is a console error like 'jQuery is not defined'. Every optimisation plugin has an exclusion list; add the handle the inline code depends on (usually jquery-core) and defer the rest.
Should I use 'Remove Unused CSS' or 'Load CSS asynchronously'?
Remove Unused CSS (WP Rocket, LiteSpeed's UCSS, Perfmatters) produces a per-page stylesheet containing only the rules the page uses and inlines it; it is the larger win when it works. Load CSS asynchronously with critical CSS is the older technique and is the fallback when unused-CSS removal breaks a page's styling. Try the first; keep the second for the pages it breaks.
Do I need a paid plugin?
No. Autoptimize is free and does aggregation, deferral and critical CSS; LiteSpeed Cache is free on LiteSpeed servers; the dequeue and defer code in the companion guide is a dozen lines. Paid plugins add per-page switches and delay-until-interaction, which is convenient rather than necessary.

Check a page against this

Runs the same Core Web Vitals test as the WordPress plugin speed test.

Free, no signup, no ads. We keep nothing except the shareable result, for 30 days.

Enter any public URL. You’ll get the one change that recovers the most load time, what it’s worth, and the measurements underneath.

Related guides

All guides