Quick answer: Render-blocking resources are CSS and synchronous scripts in the head that the browser must process before painting anything. Eliminate them by inlining critical above-the-fold CSS, loading the rest non-blocking, and adding defer or async to scripts. This usually improves both First and Largest Contentful Paint.
The browser can't render anything until it finishes downloading and parsing every render-blocking CSS and synchronous JS in the <head>. Each blocking resource adds latency to FCP and LCP.
TL;DR
- What: CSS and synchronous
<script>tags in<head>that block the browser from rendering. - Target: Zero render-blocking resources on the critical path. Inline critical CSS, defer the rest.
- Top three fixes: inline critical CSS, defer non-critical stylesheets, add
defer/asyncto scripts.
What is render blocking?
Render blocking is when the browser has to stop building the page and wait for a file to download and process before it can paint anything on screen. The browser parses your HTML from top to bottom, and certain resources in the <head> halt that parse until they finish. Nothing is visible to the user while that wait happens, which is why render-blocking resources are the most common cause of a slow First Contentful Paint.
What is a render-blocking script? A <script> tag in the <head> without a defer or async attribute. The browser must download it, execute it, and only then continue parsing the HTML, because the script could modify the document.
What is render-blocking CSS? Any <link rel="stylesheet"> without a media condition. CSS is render blocking by design: the browser refuses to paint until it knows the styles, so it cannot show unstyled content and then restyle it.
The distinction that matters: render blocking is not the same as slow. A 200 KB stylesheet that loads in parallel with nothing waiting on it costs you nothing visually. The same file in the <head> costs you your entire first paint. Position and attributes decide whether a resource blocks, not size.
What does the render-blocking-resources audit check?
Lighthouse identifies every CSS link tag and synchronous <script> in <head> that delays the first paint. It estimates how much time you'd save by deferring each one.
Why do render-blocking resources matter?
The browser parses HTML top-down. When it hits:
<link rel="stylesheet" href="big-app.css" />
…it stops, downloads big-app.css, parses it, then continues. If your CSS is 200 KB on a slow network, that's a 1-2 second pause before any pixels paint. Same for synchronous JS in <head>.
How do I check for render-blocking resources?
You do not need a dedicated checker tool. Three reliable ways:
- PageSpeed Insights or Lighthouse: run the audit and open "Eliminate render-blocking resources" under Opportunities. It lists every blocking file with its URL, transfer size, and the estimated milliseconds you would save by deferring it. That list is your fix queue, already ranked.
- Read your own
<head>in view-source. Every<link rel="stylesheet">without amediaattribute and every<script>withoutdeferorasyncis render blocking. This takes about thirty seconds and catches most of it. - Chrome DevTools Network panel: load the page, sort by start time, and look at what completes before first paint. Anything downloading in that window while nothing renders is in the critical path.
The DevTools Coverage tab is a useful companion: it shows how much of each blocking stylesheet the page actually uses. A stylesheet that blocks first paint and is 90% unused is the highest-value thing on the list.
How do I eliminate render-blocking resources?
1. Inline critical CSS
"Critical CSS" = the styles needed to render the above-the-fold portion of the page. Inline it directly in <head>:
<head>
<style>
/* critical: header, hero, primary nav */
body { margin: 0; font-family: system-ui; }
header { padding: 16px; background: #fafaf9; }
h1 { font-size: 2rem; }
</style>
<link rel="preload" as="style" href="/full.css" onload="this.rel='stylesheet'" />
</head>
For larger sites, tools like Critical, Penthouse, or framework features (Next.js does this automatically in some configurations) extract critical CSS at build time.
2. Defer non-critical CSS
<!-- WRONG: blocks rendering -->
<link rel="stylesheet" href="/non-critical.css" />
<!-- RIGHT: load asynchronously, apply after parse -->
<link rel="preload" as="style" href="/non-critical.css" onload="this.rel='stylesheet'" />
<noscript><link rel="stylesheet" href="/non-critical.css" /></noscript>
The onload swap converts the preload into a stylesheet once it's loaded, without blocking. The <noscript> fallback ensures JS-disabled users still get styles.
3. Add defer or async to scripts
<!-- WRONG: blocks the parser -->
<script src="app.js"></script>
<!-- defer: runs after document parse, preserves order -->
<script src="app.js" defer></script>
<!-- async: runs whenever it's downloaded (no order guarantee) -->
<script src="analytics.js" async></script>
Rule of thumb:
deferfor scripts that need DOM access and depend on each other (your app code)asyncfor independent scripts that don't depend on order (analytics, error tracking)- Move below
</body>if you can't use either, old-school but still works
4. Load fonts strategically
Web fonts are a common silent render-blocker. Best practice:
<head>
<!-- preconnect to the font origin so DNS/TLS is warm -->
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<!-- preload the most critical font file (typically the body font) -->
<link rel="preload" as="font" type="font/woff2"
href="https://fonts.gstatic.com/.../inter.woff2" crossorigin />
<!-- load the CSS asynchronously -->
<link rel="preload" as="style"
href="https://fonts.googleapis.com/css2?family=Inter"
onload="this.rel='stylesheet'" />
</head>
Or self-host fonts and use font-display: swap so text renders with a fallback font immediately.
What are common render-blocking mistakes?
- Inlining the entire stylesheet. That gives you all of it on every page even if 90% is unused. Inline only critical (~5–10 KB).
- Defer-loading critical CSS. If your above-the-fold renders unstyled (FOUC), critical CSS isn't inlined, fix that first.
- Forgetting
<noscript>fallback for the preload+onload pattern. JS-disabled users will see unstyled content otherwise.
How do I verify render-blocking is fixed?
- Re-run Lighthouse,
render-blocking-resourcesaudit should pass or show much smaller estimated savings. - Check
first-contentful-paintandlargest-contentful-paintaudits, both should improve. - DevTools → Network → throttle to Slow 3G → reload. The page should paint within ~1-2 seconds even on slow connections.
Related audits
- Largest Contentful Paint (LCP), downstream of render-blocking fixes
- Reduce unused JavaScript, trim what does load
- Total Blocking Time (TBT), main-thread blocking
Audit your URL at https://lighthouse-md.com.
Audit your page now
Paste your URL, get scores plus a CLAUDE.md plan for Claude Code.