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 the audit checks
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 it matters
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>.
Three fix tactics
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.
Common 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.
Verification
- 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.