How to Fix Render-Blocking Resources
Render-blocking CSS and JavaScript delay the first paint of your page. Learn how to identify and eliminate them to dramatically speed up FCP and LCP.
Render-blocking resources are CSS and JavaScript files that prevent the browser from painting the page until they’ve finished downloading and executing. They’re one of the most common causes of slow First Contentful Paint (FCP) and Largest Contentful Paint (LCP).
The fix varies depending on whether the resource is CSS or JavaScript — and whether it’s critical or not.
Why Resources Block Rendering
Browsers are conservative. They won’t render any content until they have all the CSS needed to style it (because rendering it without styles would cause a layout shift). They also won’t run JavaScript that might modify the DOM before other scripts have run.
So by default:
- All CSS in
<link>tags blocks rendering - All
<script>tags withoutasyncordeferblock rendering
If you have 500KB of CSS and 200KB of JavaScript loading before the first paint — and those files live on a slow server — your FCP will be measured in seconds, not milliseconds.
Identifying Render-Blocking Resources
In a debugutils.dev speed report, the request waterfall shows the critical rendering path. Look for:
- CSS and JS resources that start loading immediately (near the top of the waterfall)
- Long bars for these resources before the first paint marker
- The Lighthouse recommendations section will explicitly call out “Eliminate render-blocking resources”
Fixing Render-Blocking CSS
You can’t just defer CSS — you need it to render the page. The solution is to split CSS into critical and non-critical.
Critical CSS — the styles needed to render above-the-fold content. Inline this directly in the <head>.
Non-critical CSS — everything else. Load it asynchronously.
Inline critical CSS
<head>
<style>
/* Only the styles needed for above-the-fold content */
body { margin: 0; font-family: sans-serif; }
.hero { background: #000; color: #fff; padding: 4rem 2rem; }
.hero h1 { font-size: 3rem; margin: 0; }
</style>
<!-- Load full stylesheet without blocking -->
<link rel="preload" href="styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'" />
<noscript><link rel="stylesheet" href="styles.css" /></noscript>
</head>
Tools like Critical can automate the extraction of critical CSS.
Use media queries to defer non-critical CSS
CSS for print, dark mode, or large screens can be marked as non-blocking:
<link rel="stylesheet" href="print.css" media="print" />
<link rel="stylesheet" href="large-screens.css" media="(min-width: 1200px)" />
These still download but don’t block the first render.
Fixing Render-Blocking JavaScript
JavaScript is more straightforward. Use defer or async on any script that doesn’t need to execute before the page renders.
defer — recommended for most scripts
<script src="app.js" defer></script>
defer downloads the script in parallel with HTML parsing but only executes it after parsing is complete, in order. This is the right choice for most application JavaScript.
async — for truly independent scripts
<script src="analytics.js" async></script>
async downloads and executes as soon as the script is ready, without waiting for HTML parsing. Use for scripts that don’t depend on DOM or other scripts (analytics, ad scripts).
Move scripts to the end of <body>
If you can’t use defer or async, placing scripts just before </body> ensures they don’t block the initial render.
Avoid synchronous third-party scripts
Some third-party snippets are provided as synchronous scripts in the <head>. Where possible, load these with async or wrap them in a setTimeout to delay execution.
The Impact of Fixing Render-Blocking Resources
On a typical site, eliminating render-blocking resources improves FCP by 0.5–2 seconds. Lighthouse estimates the time savings for each blocking resource in its “Opportunities” section.
Start with the largest files — they have the most impact. Even a single 200KB synchronous script can add a full second to FCP on a mobile connection.