"Eliminate render-blocking resources" is the single most common warning in a PageSpeed Insights report on a WordPress site. It shows up because WordPress themes and plugins default to loading their CSS and JavaScript synchronously in the `<head>`, which forces the browser to download and process those files before it can render anything at all - including your LCP element.
This guide is a WordPress-specific playbook for that warning: what the theme and plugin patterns behind it actually look like, how to find the specific files blocking your site, and the ordered set of fixes that work without breaking layout or interactivity. For the general definition of the concept, see the render-blocking resources glossary entry.
TL;DR
The PSI warning "eliminate render-blocking resources" on WordPress usually points to three culprits: the theme's main stylesheet, plugin CSS files enqueued in the head, and synchronous JavaScript loaded by plugins or a page builder. Fix in this order: generate critical CSS and load the rest asynchronously (WP Rocket, LiteSpeed Cache, and FlyingPress automate this), add defer to non-essential JavaScript, delay analytics and chat widgets until interaction, conditionally dequeue plugin assets on pages that do not need them, and handle jQuery dependencies carefully so you do not break the site. Always test on staging first, keep a per-page exclude list, and run visual regression before pushing to production.
Key Takeaways
- ✓In WordPress, the render-blocking warning almost always points to the theme stylesheet, plugin CSS/JS enqueued in the head, and jQuery-based scripts loaded synchronously.
- ✓Critical CSS (inline the above-the-fold styles, async-load the rest) is the highest-ROI fix and is automated by WP Rocket, LiteSpeed Cache, and FlyingPress.
- ✓Adding `defer` to JavaScript is safe for most non-jQuery scripts. Delaying scripts until user interaction is safer still for analytics, chat, and tag manager.
- ✓Conditionally dequeueing plugin assets on pages that do not need them (Perfmatters, Asset CleanUp) often removes 4-8 render-blocking files at once.
- ✓jQuery dependencies are the most common thing to break. Any script that expects jQuery to be loaded first cannot be deferred without adding it to an exclude list.
- ✓Never optimize on production without a staging test and a visual regression pass. A broken menu or missing checkout button costs more than a slow page.
What the PSI Warning Means in WordPress Terms
PageSpeed Insights flags a resource as render-blocking when it is a stylesheet or a synchronous script in the `<head>` that the browser has to download and process before it can render the first pixel. On WordPress, that almost always means one of the following.
The theme's main stylesheet (typically `style.css` or a bundled `main.css`). It is enqueued in the head with `wp_enqueue_style` and loads synchronously. On a well-built theme it is 20-60 KB. On a multipurpose theme with a page builder it is 200-500 KB.
Plugin CSS files enqueued site-wide. Every plugin that has front-end UI (contact forms, sliders, reviews, WooCommerce extensions, cookie banners) typically loads its own stylesheet in the head on every page, whether the plugin runs on that page or not. Ten active plugins routinely means ten additional render-blocking CSS files.
Synchronous JavaScript. jQuery, jQuery Migrate, jQuery UI, and plugin JavaScript that a developer forgot to defer. Even a small 5 KB script blocks HTML parsing if it is loaded synchronously in the head.
Google Fonts loaded via a blocking `<link>` in the head. The stylesheet request from `fonts.googleapis.com` blocks rendering, and then the actual font files block text painting.
Eliminating render-blocking on WordPress is really about fixing these four patterns.
Find the Culprits
Before changing anything, identify the specific files blocking your specific site. Guessing wastes time and often breaks something unrelated.
PageSpeed Insights. Run PSI on a representative page (usually your homepage and one product or post). The Opportunities section will list "Eliminate render-blocking resources" with each specific file, its transfer size, and the estimated LCP savings from removing it. This is your target list.
Chrome DevTools Coverage tab. Open DevTools, press Ctrl+Shift+P, type "Show Coverage", and reload the page. Coverage shows every CSS and JS file loaded and what percent of each is actually used. A stylesheet with 92% unused bytes on the homepage is almost certainly being loaded by a plugin that has no reason to run there.
Our free render-blocking finder. The render-blocking finder tool crawls a URL and lists every render-blocking resource with its size and origin, without needing to open DevTools.
The output of this step is a list of specific files you are going to unblock, defer, delay, or dequeue. Do not skip it.
1. Critical CSS Plus Asynchronous Full Stylesheet
The biggest single win is separating the CSS the browser needs to render the above-the-fold view from the rest of the stylesheet. Extract the critical (above-the-fold) rules, inline them in the `<head>`, and load the full stylesheet asynchronously so it does not block rendering.
<style>/* inlined critical CSS: 8-20 KB */</style>
<link rel="preload" as="style" href="/style.css" onload="this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="/style.css"></noscript>
Doing this by hand for a WordPress site is painful because every template needs a different critical CSS payload. Use a caching plugin that automates it.
WP Rocket ships a "Remove Unused CSS" feature that generates per-template critical CSS on the fly and async-loads the rest.
LiteSpeed Cache ships "CCSS" (Critical CSS) as part of its optimization suite, tied to its QUIC.cloud service.
FlyingPress ships "Generate Critical CSS" and "Lazy Render HTML" that together do the same job with less configuration.
See the comparison in best WordPress speed plugins for which one fits your stack. Whichever plugin you use, always test on staging first because plugin-generated critical CSS occasionally misses styles used in menus, modals, or accordions and causes a flash of unstyled content.
2. Defer JavaScript
The `defer` attribute tells the browser to download the script in parallel with HTML parsing but only run it after parsing is done. This removes the script from the render-blocking path without changing its execution order relative to other deferred scripts.
<script src="/plugin.js" defer></script>
Defer is safe for almost every script except those that expect jQuery to be already defined when they run (see the jQuery section below).
How to defer in WordPress. WP Rocket, LiteSpeed Cache, and FlyingPress all have a "Load JavaScript deferred" toggle that adds `defer` to every enqueued script. If you are not using a plugin, add a `script_loader_tag` filter in your theme's functions.php that adds `defer` to matching handles.
Do not use `async` for anything except analytics. `async` runs the script as soon as it downloads, in whatever order they arrive, which frequently breaks anything that depends on load order (jQuery plugins, framework components).
3. Delay JavaScript Until Interaction
Analytics, tag manager, chat widgets, heatmaps, and marketing pixels never need to run before the user interacts with the page. Delaying them until the first scroll, mouse move, or touch removes them from the initial LCP window entirely and dramatically improves both LCP and INP. This matters because the median page now ships 375 KB of third-party JavaScript, roughly two-thirds of all JS on a typical WordPress site, and almost none of it is needed for first paint.
This is different from `defer`. Deferred scripts still run after HTML parsing completes; delayed scripts do not run until the user does something.
WP Rocket ships "Delay JavaScript Execution" with a default exclude list.
FlyingPress ships "Delay JavaScript" with per-script granularity.
Perfmatters ships "Delay JavaScript" with a pattern-matching UI.
Do not delay JavaScript that your first paint depends on (theme framework runtime, cookie consent banners in some regions, above-the-fold sliders). The delay lists in the plugins above ship with sensible defaults; extend them cautiously.
4. Conditionally Load Plugin Assets
The cleanest fix for a plugin CSS or JS file that loads on every page but is only used on one is to stop loading it on the pages that do not need it. WordPress core does not support this out of the box, but two plugins do.
Perfmatters ships a script manager with a UI that lets you disable each plugin's scripts on a per-page, per-post-type, per-URL-pattern, or site-wide basis.
Asset CleanUp does the same job with a slightly different UI. It also detects and lets you disable unused CSS and JS on each page individually.
Typical wins: disable the contact form plugin on every URL except the contact page, disable the WooCommerce cart fragments script on non-shop pages, disable page builder CSS on posts and pages not built with the builder. Each dequeue removes one render-blocking resource from the page's list.
Always verify on staging. It is easy to accidentally dequeue an asset that a header or footer widget depends on.
5. Handle jQuery Dependencies Safely
jQuery is the most common thing to break when eliminating render-blocking resources. WordPress core loads jQuery in the head by default, and hundreds of plugins and themes assume it is present and defined before their own inline scripts run.
What breaks. If you defer jQuery, any inline script that runs `jQuery(function($){ ... })` before the deferred jQuery has loaded will throw "jQuery is not defined" and stop executing. Menus, sliders, tabs, and form validation are common victims.
Safe options.
Leave jQuery undeferred but defer everything else. Most speed plugins' "defer JavaScript" toggles ship with jQuery on the exclude list for this exact reason.
Move jQuery to the footer. Setting `wp_scripts()->add_data('jquery', 'group', 1)` moves it out of the render-blocking path in the head. Works only if no theme or plugin inline scripts in the head expect jQuery to exist.
Audit and remove jQuery dependency where possible. Modern themes (GeneratePress, Blocksy, Kadence, Bricks) do not require jQuery in the front-end. If your theme is one of these, you can dequeue jQuery entirely on pages where no plugin needs it.
When in doubt, exclude jQuery from defer, ship the rest of the optimizations, and revisit jQuery once everything else is stable.
6. Fonts: Preload and font-display: swap
Web fonts are technically not "render-blocking resources" in the PSI sense (they do not block first paint) but they are text-render-blocking, which delays LCP when the LCP element is a heading.
Add `font-display: swap` to every @font-face rule so the browser paints text immediately in a fallback and swaps in the webfont when it arrives.
Preload the font file used above the fold.
<link rel="preload" as="font" type="font/woff2" href="/fonts/inter.woff2" crossorigin>
Self-host Google Fonts instead of loading from `fonts.googleapis.com`. Self-hosting removes an extra DNS lookup and TCP connection (typically 100-300 ms) and lets you preload the font file directly. WP Rocket, LiteSpeed Cache, and OMGF (Optimize My Google Fonts) all automate the self-hosting step.
For the extraction concept underlying critical CSS, see the critical CSS glossary entry.
Test-Safely Checklist
Every one of these fixes can break something visible. Follow this before you ship any change to production.
Always test on staging first. Never enable critical CSS, defer JavaScript, delay JavaScript, or dequeue plugin assets on a live site without a staging copy to test on.
Keep a per-page exclude list. Critical CSS occasionally misses styles used in menus, modals, or accordions. Every speed plugin lets you exclude URLs from optimization; use it for pages where the automated fix produces a visible issue.
Visual regression before pushing. Open the homepage, one product page, one blog post, the cart, the checkout, and the contact page in incognito with the optimizations on. Look at every above-the-fold section for missing background images, unstyled text, or shifted layout. Interact with every menu, modal, filter, and form.
Watch INP and LCP in field data. A defer or delay change occasionally makes INP worse (because a script now runs later, right when the user tries to interact). Watch the 75th-percentile numbers for a week after shipping.
Keep a rollback plan. Every optimization plugin above has an "exclude URL" or "disable optimization" button. Know how to hit it fast if something breaks on the live site.
Frequently Asked Questions
What are render-blocking resources in WordPress?
In WordPress, render-blocking resources are almost always the theme's main stylesheet, plugin CSS files enqueued in the head, synchronous JavaScript (often jQuery and jQuery-dependent plugin scripts), and Google Fonts loaded via a blocking link tag. Any of these that sits in the head without defer or async prevents the browser from rendering the first pixel until they finish downloading and parsing.
Does WP Rocket remove render-blocking resources?
Yes. WP Rocket ships "Remove Unused CSS" (generates per-template critical CSS and async-loads the full stylesheet), "Load JavaScript deferred" (adds defer to enqueued scripts), and "Delay JavaScript execution" (delays non-essential scripts until user interaction). Together these address the three main render-blocking causes in a typical WordPress install. LiteSpeed Cache and FlyingPress ship equivalent features.
Can removing render-blocking resources break my site?
Yes, and it commonly does on the first attempt. Critical CSS occasionally misses styles used in menus, modals, or accordions and causes a flash of unstyled content. Deferring jQuery breaks any inline script that assumes jQuery is already defined. Delaying JavaScript breaks widgets that need to run before user interaction. Always test on staging first, keep a per-page exclude list, and run visual regression on your most important templates (homepage, product, checkout) before pushing to production.
Do I still need this on a fast theme?
Somewhat less, but usually still yes. A fast theme like GeneratePress or Blocksy ships far less CSS and JavaScript than a multipurpose theme, so the theme's own contribution to render-blocking is minor. But the plugins you install on top still enqueue their own CSS and JS on every page. Even on a lean theme, conditionally dequeueing plugin assets and delaying analytics or tag manager typically shaves 200-600 ms off LCP.