Skip to content
ThemesIonic — home
Troubleshooting

How to Fix Render-Blocking Resources in WordPress

The browser stops painting while it fetches stylesheets and head scripts. Load less CSS, defer scripts, and stop third-party tags from sitting in the critical path.

1 min read advanced

Start by removing, not deferring. The fastest asset is the one that is never requested. Most WordPress sites load stylesheets and scripts from plugins on pages that do not use them, and dequeuing those beats any amount of clever loading.

See what is actually blocking

Open DevTools, reload with the Network tab recording, and sort by the order requests are made. Anything fetched in the head before the first paint is in the critical path.

The page-speed report's "Eliminate render-blocking resources" list gives you the same information with estimated savings. Treat the estimate as a rough guide; the file names are the useful part.

Typical findings on a WordPress site:

Asset Usually from
style.css The theme — necessary
Several small plugin stylesheets Contact forms, sliders, cookie banners
jQuery in the head An older theme or plugin
A font stylesheet from a third party Google Fonts or similar
Analytics and tag manager Marketing tags
Icon font CSS The theme's icon set

Step 1: stop loading what the page does not use

A contact form stylesheet does not belong on the homepage. Dequeue it conditionally in a site-specific plugin:

<?php
add_action('wp_enqueue_scripts', function () {
    if (! is_page('contact')) {
        wp_dequeue_style('contact-form-styles');
        wp_dequeue_script('contact-form-scripts');
    }
}, 100);

Find the handle by looking at the enqueue call in the plugin, or by printing the registered handles during development. The priority of 100 matters — dequeue after the plugin has enqueued.

Some optimisation plugins offer this as a per-page interface, which is easier to maintain than code and does the same thing.

Better still: remove plugins you barely use. Each one is assets, database queries and updates — see how to delete a plugin completely.

Step 2: defer JavaScript

Scripts in the head block parsing unless marked otherwise:

  • defer — download in parallel, execute after HTML parsing, in order. The right default for most site scripts.
  • async — download in parallel, execute as soon as ready, order not guaranteed. Suitable for independent third-party tags.
<?php
add_filter('script_loader_tag', function (string $tag, string $handle): string {
    $defer = ['theme-main', 'slider', 'lightbox'];

    return in_array($handle, $defer, true)
        ? str_replace(' src', ' defer src', $tag)
        : $tag;
}, 10, 2);

Do not defer inline scripts that depend on a deferred file, and be careful with jQuery: deferring it while an inline script uses $ immediately produces a console error and a broken page. Test menus, sliders, forms and carts after any change — the symptoms are in WordPress menu not showing.

Step 3: reduce CSS in the critical path

Options, from safest to most invasive:

  1. Load non-critical CSS with a non-matching media attribute, so it does not block:

    <link rel="stylesheet" href="print.css" media="print">
    
  2. Minify. Reliable and low risk.

  3. Inline critical CSS and load the rest asynchronously. Effective, but the generated critical CSS goes stale whenever the design changes, and a wrong result shows an unstyled flash.

  4. Remove unused CSS. The biggest wins and the biggest risk — tools frequently strip rules used by states, interactions or logged-in views. If you enable it, test hover states, mobile menus, form validation messages and the cart.

Most performance plugins offer options 2 to 4. Enable one at a time and check the site between each, as choosing a cache plugin recommends.

Step 4: fix fonts

Third-party font stylesheets add a DNS lookup, a connection and a blocking request.

  • Self-host the font files where the licence permits, and reference them from your own stylesheet.
  • Preload the one or two files used above the fold.
  • Use font-display: swap so text renders immediately.
  • Subset to the characters you need if the family is large.

This also removes the layout shift that font swapping causes, per how to fix cumulative layout shift.

Step 5: get third-party tags out of the head

Analytics, chat widgets, heat maps, ad scripts and consent tools are often the largest blocking cost, and none of them need to run before the page paints.

  • Load them with async at minimum.
  • Delay them until user interaction where the vendor supports it.
  • Audit them: measure the page with each removed, and remove the ones nobody uses.

A chat widget that costs half a second of load time on every page, for a handful of conversations a month, is worth a conversation with whoever asked for it.

What not to bother with

  • Combining files. Under HTTP/2 the benefit is small and the breakage is real.
  • Chasing a perfect score. A page that paints in a second with a score of 88 beats one at 99 that took a week.
  • Optimising a page nobody visits. Fix the templates that carry your traffic first.

Verify

Re-test the same page, logged out, with the cache warm, and compare the blocking list. Then check the visual result at a slow connection setting in DevTools — a page that scores better but flashes unstyled content has traded one problem for another. The wider sequence is in how to speed up a WordPress site.

Frequently asked

Stylesheets loaded normally in the head are, by design — the browser avoids painting unstyled content. CSS loaded with a media query that does not match, or loaded asynchronously, is not.
Rarely worth it now. With HTTP/2 the request cost is small, and combining is the most common cause of broken menus, sliders and forms.
The minimum styles needed to render what is visible before scrolling, inlined in the head so the page paints immediately while the full stylesheet loads asynchronously.

Related guides