Eliminate Render-Blocking Resources: How to Fix It
- August 22, 2025
- Performance, Resource Loading

What "Eliminate render-blocking resources" actually flags
This check fires when your page loads CSS or JavaScript in a way that halts rendering. A synchronous <script> or a stylesheet in the <head> forces the browser to stop, fetch, and process that file before it can paint a single pixel. Until every blocking resource in the head resolves, your visitor stares at a blank screen. Lighthouse lists each blocker and estimates the milliseconds you would reclaim by unblocking it.
The stakes hit First Contentful Paint and Largest Contentful Paint (LCP) directly, since nothing renders until the head clears. On slow connections a handful of blocking files can push first paint back by seconds, which is exactly where impatient users bail.
A real failing example (and the fix)
Here the head blocks on a full stylesheet and a synchronous script, both of which stall the first paint:
<head>
<!-- Blocks paint until the whole file downloads and parses -->
<link rel="stylesheet" href="/css/app.css">
<!-- Blocks parsing AND paint right here in the head -->
<script src="/js/bundle.js"></script>
</head>Fix the script first, it almost never needs to block. Move it out of the critical path with defer (runs after HTML parses, in order) or async (runs whenever it arrives, for independent scripts):
<head>
<script src="/js/bundle.js" defer></script>
</head>For CSS, inline the small slice needed for above-the-fold content and load the rest without blocking. The media="print" swap is a reliable trick to fetch a stylesheet asynchronously, then apply it once loaded:
<head>
<style>/* critical above-the-fold CSS, kept small */</style>
<!-- Load the rest without blocking paint -->
<link rel="stylesheet" href="/css/app.css"
media="print" onload="this.media='all'">
<noscript><link rel="stylesheet" href="/css/app.css"></noscript>
</head>Why the head is a bottleneck
Browsers build a page in a strict order: parse the HTML, build the DOM, apply the CSSOM from your stylesheets, then paint. A blocking resource in the <head> jams a stop sign into that pipeline. The parser reaches your synchronous <script> and refuses to move on until the file is downloaded, parsed, and executed, because that script might rewrite the very HTML that follows it. A stylesheet blocks painting for the same reason: the browser will not risk flashing unstyled content, so it waits for the CSS. That is why two or three files in the head, each needing its own round trip on a slow connection, can hold the screen blank for whole seconds while the rest of your beautifully optimized page sits ready and waiting.
defer vs. async vs. blocking
| Attribute | Blocks HTML parsing? | Execution timing | Use for |
|---|---|---|---|
| none (default) | Yes | Immediately, in place | Almost nothing in the head |
defer | No | After parse, in document order | Most app/site scripts |
async | No | As soon as it downloads | Independent tags (analytics) |
| inline critical CSS | No (already present) | N/A | Above-the-fold styles |
media="print" swap | No | On load | Non-critical stylesheets |
How to detect it on your own site
- Lighthouse: the "Eliminate render-blocking resources" opportunity names every blocking URL and the estimated savings in milliseconds for each, so you can prioritize the biggest wins.
- PageSpeed Insights: the same opportunity appears at pagespeed.web.dev, tied to your field LCP so you know whether blocking is what is actually delaying real users.
- DevTools Coverage tab: open Coverage (Cmd/Ctrl+Shift+P, "Show Coverage"), reload, and see how much of each blocking CSS/JS file is unused, that unused chunk is a prime candidate to split out and defer.
- WebPageTest: the waterfall shows blocking requests stacked before Start Render. Anything to the left of that green line is delaying your first paint.
How to fix it, step by step
- Add
deferto scripts that need DOM order, orasyncto independent third-party tags; move both out of blocking position. - Extract the critical above-the-fold CSS, inline it in the head, and keep it lean.
- Load the remaining CSS non-blocking with the
media="print"/onloadpattern (plus a<noscript>fallback). - Split large bundles so each page ships only the CSS and JS it needs; delete unused code (remove unused JavaScript).
- Preload genuinely critical assets (a hero font or LCP image) so they start early without blocking parse.
- Re-run Lighthouse and confirm the blocking list shrinks and FCP/LCP improve.
FAQ
Should I just defer every script?
Defer is the safe default for most site scripts because it preserves execution order and waits for the DOM. Use async only for scripts that do not depend on the page or each other, like an analytics beacon. Inline scripts that must run before paint (rare) stay put.
Is inlining CSS bad for caching?
Inlined critical CSS is not cached separately, but it is tiny by design and it removes a blocking round trip. The bulk of your stylesheet still loads as a cacheable external file. The tradeoff favors inlining the small critical part.
Do blocked resources hurt crawling or just speed?
Mostly speed and Core Web Vitals. But if you go the other way and block CSS/JS from crawlers in robots.txt, that does break rendering for Google, see disallowed stylesheet. Deferring for users and disallowing for bots are different problems.
Will a CDN solve render-blocking?
A CDN makes blocking files arrive faster, which helps, but a resource in the critical path still blocks. You have to change how it loads, not just where it loads from.
How does this tie into Core Web Vitals?
Render-blocking directly delays paint, which pushes out LCP, one of the three Core Web Vitals. Clearing the critical path is one of the highest-leverage LCP fixes there is.
How do I know which CSS is "critical"?
Critical CSS is only the styling needed to render what is visible above the fold on first paint, the header, hero, and initial layout, not your footer or modal styles. You can extract it by hand from the styles those elements use, or generate it with a critical-CSS tool that loads the page, records which rules apply to the visible viewport, and inlines just those. Keep it small; if your "critical" block balloons, you have defeated the point and are back to shipping most of the stylesheet inline.
Does WordPress handle this automatically?
Not out of the box, but caching and optimization plugins can defer JavaScript, inline critical CSS, and load the rest asynchronously with a few toggles. Test after enabling, aggressive deferral occasionally breaks a script that expected to run early. See speed up WordPress for the safe settings.
Claude Vincent is a technical SEO consultant focused on crawlability, rendering, and AI-search visibility. He writes the field guides and case studies at SEO ProCheck, with a bias toward the durable, unglamorous work that decides whether search engines and AI answer engines can actually read and cite a site.
About SEO ProCheck
Technical SEO consulting and GEO strategy with 20 years of enterprise experience. Case studies, resources, and tools for search and AI visibility.
Work With Me
Technical SEO audits, GEO strategy, site migrations, and international SEO. Hourly consulting for teams who need hands-on support, not just reports.







