Eliminate Render-Blocking Resources in WordPress: How to Fix It
PageSpeed Insights flags render-blocking resources when CSS or JavaScript files in the head of your page must download and be processed before the browser is allowed to show anything. On a WordPress site these files rarely come from you directly. They are added by the theme and by every plugin that enqueues a stylesheet or script, often on every page whether it is needed there or not. The result is a blank screen for longer, a later first paint and a slower Largest Contentful Paint, especially on mobile. This guide shows you how to trace each flagged file to the plugin or theme that loads it, remove what is not needed, defer scripts without breaking menus and forms, handle jQuery and critical CSS, and confirm the fix across your templates.
What render-blocking means in WordPress
When the browser reads the head of your HTML and meets a normal stylesheet link or a script tag without defer or async, it stops. A stylesheet must be downloaded and parsed before the page is painted, so nothing appears until it arrives. A plain script must be downloaded and run before the browser even continues reading the HTML. Each blocking file adds at least one network round trip before the first paint, and on a phone over mobile data that adds up quickly.
In current versions of PageSpeed Insights this appears as the Render-blocking requests insight; older reports call it Eliminate render-blocking resources. Both list each file with its size and an estimate of the time it costs. Treat the estimate as a guide, not a promise, because removing one file can expose the next.
WordPress makes the problem common because of how assets are added. Each plugin calls wp_enqueue_style and wp_enqueue_script to add its files, and many do so on every page so that their feature works wherever you might use it. A site with twenty plugins can easily load fifteen stylesheets and a dozen scripts in the head of a simple blog post. The general principles are covered in the render-blocking resources guide; this page focuses on WordPress.
How to trace each file to its plugin or theme
The URL of each flagged file usually tells you where it came from:
| Path in the URL | Comes from | Typical action |
|---|---|---|
/wp-content/plugins/contact-form-7/ | That plugin | Load only on pages that use it |
/wp-content/themes/your-theme/ | The theme | Theme settings, child theme or critical CSS |
/wp-includes/css/dist/block-library/ | WordPress block styles | Keep if you use the block editor |
/wp-includes/js/jquery/ | jQuery, loaded for a theme or plugin | Handle with care, see below |
fonts.googleapis.com | Theme or page builder font setting | Host fonts locally |
/wp-content/cache/ | Files combined by a caching plugin | Check its CSS and JS settings |
To find the handle WordPress uses for a file, view the page source. Stylesheets carry an id made of the handle plus -css, and scripts carry the handle plus -js:
<link rel="stylesheet" id="contact-form-7-css" href="https://example.com/wp-content/plugins/contact-form-7/includes/css/styles.css" media="all">
<script src="https://example.com/wp-content/plugins/contact-form-7/includes/swv/js/index.js" id="swv-js"></script>
Here the handles are contact-form-7 and swv. The Query Monitor plugin also lists every enqueued script and style on a page with its handle, its dependencies and the component that added it, which is quicker on a busy site.
Stop plugins loading files where they are not used
The best render-blocking file is one that is never loaded. Start by deleting plugins you no longer use, then stop the rest from loading on pages that do not need them.
Many plugins have their own setting for this. Others can be controlled with a script manager such as the one in Perfmatters or the Asset CleanUp plugin, which let you turn files off per page or per post type. If you prefer code, dequeue the files in your child theme's functions.php or a small site plugin:
add_action( 'wp_enqueue_scripts', function () {
if ( ! is_page( 'contact' ) ) {
wp_dequeue_style( 'contact-form-7' );
wp_dequeue_script( 'contact-form-7' );
wp_dequeue_script( 'swv' );
}
}, 100 );
The priority of 100 makes the function run after the plugin has enqueued its files. Contact Form 7 also offers its own filters, wpcf7_load_js and wpcf7_load_css, for the same purpose. Always check the page that does use the plugin afterwards, and send a test form.
Defer scripts the WordPress way
Since WordPress 6.3, scripts can be registered with a loading strategy. WordPress adds the attribute and keeps dependencies in a safe order:
wp_enqueue_script(
'site-menu',
get_stylesheet_directory_uri() . '/js/menu.js',
array(),
'1.2.0',
array( 'strategy' => 'defer', 'in_footer' => true )
);
If a script with a defer strategy is a dependency of a script that must block, WordPress quietly downgrades it to blocking rather than breaking the order, so check the final HTML to see what you actually got. More detail on scripts is in render-blocking JavaScript, and on stylesheets in render-blocking CSS.
jQuery, critical CSS and fonts
jQuery is the file most likely to break things. Many themes and plugins print small inline scripts that call jQuery(...) immediately. If jQuery is deferred, those inline scripts run first and fail with jQuery is not defined, so menus, sliders and forms stop working. Defer jQuery only if every script that uses it, including inline ones, is deferred or delayed too. Caching plugins handle this differently: some keep jQuery blocking by default, while delay features hold all scripts until the first interaction. Check the browser Console for errors after any change.
Critical CSS means placing the small set of styles needed for the first screen directly in the head and loading the full stylesheet without blocking. WP Rocket, LiteSpeed Cache and Autoptimize can generate it. The usual pattern for the non-critical file is:
<link rel="preload" href="https://example.com/wp-content/themes/site/style.css" as="style"
onload="this.onload=null;this.rel='stylesheet'">
After switching it on, reload several page types and watch for a flash of unstyled content, where the page appears briefly without its design. If you see it, the critical CSS is missing rules for that template and needs regenerating.
Fonts from Google Fonts load a stylesheet from another domain, which costs an extra connection before the font file is even requested. Host the font files on your own server, preload only the main font used above the fold and use font-display: swap so text shows straight away. The font layout shift guide explains how to keep the swap from moving the layout.
Performance plugin settings
| Plugin | Settings that affect render blocking |
|---|---|
| WP Rocket | Load JavaScript deferred, Delay JavaScript execution, Remove unused CSS |
| LiteSpeed Cache | Load JS Deferred, CSS and JS minify and combine, Generate UCSS, Generate Critical CSS |
| Autoptimize | JavaScript option to defer instead of aggregate, Inline and Defer CSS |
| Perfmatters | Script manager, Delay JavaScript, Remove unused CSS |
Use one performance plugin for these features, not two. Running two that both rewrite CSS and scripts is a common cause of broken layouts and files loading twice. Combining files into one large file matters much less than it used to, because HTTP/2 handles many small files well; deferring and removing files usually gives a bigger gain.
A worked example
A small accountancy firm's WordPress site shows eleven render-blocking files in the mobile report, adding an estimated 1.4 seconds. Tracing the URLs shows a contact form plugin's CSS and two scripts, a slider plugin used only on the home page, the theme's main stylesheet, two Google Fonts stylesheets and jQuery.
The form plugin's files are dequeued everywhere except the contact page, and the slider files everywhere except the home page, using a script manager. The fonts are downloaded and served from the theme folder with font-display: swap. The theme's own scripts are switched to a defer strategy. jQuery stays as it is because the theme's menu uses inline jQuery code. The report now shows three blocking files, and mobile LCP on blog posts falls from 3.4 to 2.4 seconds.
The fix, step by step
Step 1
List the blocking files
Run PageSpeed Insights on the mobile test for the page and open the render-blocking requests insight. Copy the list of files and the time each one costs into a note. Next to each, write the plugin or theme it belongs to, using the folder in the URL such as /wp-content/plugins/ followed by the plugin name. Repeat for a blog post and a product or service page. You now have a list of exactly which components to work on, ranked by cost.
Step 2
Remove unused plugins
Go to the Plugins screen and deactivate any plugin you no longer use, then delete it. Look especially for plugins whose files appear in your list but whose feature you do not use, such as an old slider or a social sharing tool. Test the site after each removal. Run PageSpeed Insights again and confirm those files no longer appear in the render-blocking list. This is the safest change, because a deleted plugin cannot break anything it was not doing.
Step 3
Load plugin files only where needed
For plugins you keep, stop their files loading on pages that do not use them. Use the plugin's own setting if it has one, a script manager such as Perfmatters or Asset CleanUp, or wp_dequeue_style and wp_dequeue_script in a site plugin with a condition such as is_page(). Find the handles from the id attributes in the page source. Test the page that uses the feature, submit a form if relevant, and confirm the files are gone elsewhere.
Step 4
Defer your own scripts
For scripts in your theme or a small custom plugin, register them with 'strategy' => 'defer' and 'in_footer' => true in the last argument of wp_enqueue_script, which works on WordPress 6.3 or later. WordPress keeps dependencies in a safe order. View the page source and check the script tag now carries defer. Open the Console in Chrome DevTools and confirm there are no new errors, then check that menus and interactive parts still work on mobile.
Step 5
Turn on deferral in one plugin
If you use WP Rocket, LiteSpeed Cache or Autoptimize, switch on its option to defer JavaScript, one setting at a time. Leave jQuery blocking at first. Clear the cache, then test the home page, a post, the contact page and the mobile menu in a private window. If something breaks, use the plugin's exclusion box to keep that script blocking. Confirm in PageSpeed Insights that fewer scripts are listed as render-blocking without new Console errors.
Step 6
Decide what to do with jQuery
Search the page source for inline scripts that call jQuery( or $( directly. If there are any, deferring jQuery will break them unless your plugin also delays those inline scripts. Try deferring jQuery on staging, then check the Console for jQuery is not defined errors and test sliders, menus and forms. If errors appear and cannot be excluded cleanly, leave jQuery blocking. It is one file, and a working site matters more than removing it.
Step 7
Generate critical CSS
Turn on critical CSS or remove unused CSS in your performance plugin, so the styles for the first screen are inlined and the full stylesheet loads without blocking. Clear all caches and load each main template in a private window on a phone-sized screen. Watch for a brief flash of the page without its design. If you see one, regenerate the critical CSS for that template or exclude it. Confirm the theme stylesheet no longer appears in the blocking list.
Step 8
Host fonts and retest every template
Replace Google Fonts stylesheets with font files served from your own site, preload only the main font file and add font-display: swap. Many themes and performance plugins have a setting to host fonts locally. Then clear every cache and run PageSpeed Insights on the home page, a post and a product or service page. Each template loads different files, so confirm the render-blocking list is shorter on all of them and the site still works.
Edge cases worth knowing
- Different templates load different files. A product page, a blog post and the home page can each have a different set of blocking files. Test each template, not just the home page.
- Logged-in views. The admin bar and editor add their own files when you are logged in. Test in a private window.
- Cached pages after changes. Clear the page cache and any CDN cache after changing asset settings, or you may be testing the old HTML.
- Async is not always safer. Scripts with
asyncrun as soon as they arrive, in any order. Usedeferfor scripts that depend on each other. - Analytics and tags. A tag manager snippet is normally async already. If it injects blocking scripts, review the tags inside it.
Keeping it fixed
Every new plugin is a new set of files, so check the page source and the PageSpeed Insights report after installing or updating one. Keep a short list of which files you have dequeued and why, so a future developer does not undo it. Make changes on a staging site first where you can, and test forms and menus before going live.
Check the main templates in PageSpeed Insights every month, and the Core Web Vitals report in Google Search Console for real-visitor results. For wider WordPress speed work, see WordPress page speed.
1. What causes render-blocking resources in WordPress?
Render-blocking resources in WordPress are mostly caused by themes and plugins adding stylesheets and scripts to the head of every page. Each plugin enqueues its own files, often site-wide even if its feature is used on one page. Google Fonts stylesheets, page builder files, sliders and jQuery are common examples. The browser must download these before it shows anything, so the more plugins add files to the head, the longer visitors wait for the first paint, especially on mobile connections.
2. How do I defer JavaScript in WordPress without a plugin?
You can defer JavaScript without a plugin by registering scripts with a loading strategy, which WordPress has supported since version 6.3. When you call wp_enqueue_script, pass an array as the last argument with strategy set to defer and in_footer set to true. WordPress then adds the defer attribute and keeps dependent scripts in a safe order. This works for scripts in your own theme or custom plugin. For scripts from other plugins, a performance plugin or script manager is usually easier.
3. Is it safe to defer jQuery?
Deferring jQuery is safe only if every script that uses it is also deferred or delayed, including small inline scripts printed by your theme and plugins. Many WordPress sites have inline code that calls jQuery straight away, and if jQuery has not loaded yet that code fails, breaking menus, sliders or forms. Test on a staging site, check the browser Console for jQuery is not defined errors and keep jQuery blocking if you cannot resolve them cleanly.
4. Which plugin is best for fixing render-blocking resources?
There is no single best plugin; WP Rocket, LiteSpeed Cache, Autoptimize and Perfmatters can all defer scripts and handle CSS well when set up carefully. LiteSpeed Cache suits sites on LiteSpeed servers, while WP Rocket works on most hosts. What matters more is using only one of them for script and CSS changes, switching on one option at a time and testing after each change. A script manager to unload files per page often gives the biggest gain.
5. Why does PageSpeed Insights still show render-blocking resources after I installed a caching plugin?
A caching plugin speeds up how quickly the HTML is delivered, but it does not stop CSS and scripts blocking the page unless you switch on its separate file optimisation settings. Even then, some files stay blocking on purpose, such as jQuery or the critical theme stylesheet, to avoid breaking the site. Clear the page cache and any CDN cache after changing settings, test in a private window, and check whether the remaining files are ones the plugin has excluded.
6. Does combining CSS and JavaScript files help?
Combining files helps much less than it used to, and it can even make things worse. With HTTP/2 and HTTP/3, browsers download many small files in parallel efficiently, so one large combined file mainly means the whole thing must arrive before anything renders. It also makes caching less effective, because a small change produces a new combined file. Removing unused files, deferring scripts and inlining critical CSS usually give a bigger and more reliable gain.
7. Can I remove the block library CSS in WordPress?
You can remove the block library CSS only if your pages do not use blocks from the block editor, for example on a site built entirely with a classic editor and a page builder. If your content uses blocks, removing it will break their layout and spacing. Check by dequeuing the wp-block-library style on a staging site and reviewing a few posts. On block themes, WordPress already loads styles only for the blocks used on each page, which keeps the file small.
The PageSpeed checker on aiwebpageseo.com lists the CSS and JavaScript files that block rendering on your page, with the time each one costs, so you can tell which plugin to deal with first.
Open Page Speed Fixes โ