What are render-blocking resources
Resources the browser must download and process before it can render the page — primarily CSS (blocks rendering) and synchronous JS in <head> (blocks parsing). They delay first paint. Fixes: inline critical CSS, defer/async JS, load non-critical CSS lazily, minify, and use font-display.
A render-blocking resource is anything the browser must fully download and process before it can paint the page — they directly delay first paint (FCP/LCP).
The two main culprits
1. CSS — blocks rendering. The browser will not paint anything until it has built the CSSOM — it can't render an element without knowing its styles (you'd get a flash of unstyled content). So every <link rel="stylesheet"> in the <head> blocks rendering until it's downloaded and parsed. Large or slow CSS = delayed first paint.
2. Synchronous JavaScript — blocks parsing. A plain <script> (no async/defer) in the <head>:
- Pauses HTML parsing while it downloads and executes.
- And because JS can read styles, it also waits on any pending CSS above it.
So a sync script blocks both DOM construction and, transitively, rendering.
Also render-affecting: web fonts (can block text painting — FOIT) and @import in CSS (chained, serial downloads).
Why it matters
The critical rendering path can't complete until these resources are handled. They're the single biggest lever on First Contentful Paint and Largest Contentful Paint.
The fixes
CSS:
- Inline critical CSS — the styles needed for above-the-fold content go directly in a
<style>tag in the<head>; the rest loads non-blocking (mediatrick, orrel="preload"then swap to stylesheet). - Minify CSS; remove unused rules.
- Split CSS so each page ships only what it needs.
JavaScript:
defer— download in parallel, execute after HTML parsing finishes, in order. Best default for most scripts.async— download in parallel, execute as soon as ready (order not guaranteed). For independent scripts (analytics).- Move scripts to the end of
<body>, or load non-critical JS lazily.
Fonts:
font-display: swapso text renders immediately with a fallback.preloadkey fonts.
General: compress (Brotli/gzip), reduce file count, use a CDN, preconnect to critical origins.
The framing
"Render-blocking resources are ones the browser must fully process before painting. The two big ones: CSS, which blocks rendering because nothing paints until the CSSOM is built; and synchronous JS in the head, which blocks HTML parsing and transitively waits on CSS too. They're the main thing delaying FCP and LCP. The fixes: inline critical CSS and load the rest non-blocking, add defer (or async) to scripts so they don't block parsing, use font-display: swap, and minify/compress everything."
Follow-up questions
- •Why does CSS block rendering but a deferred script doesn't?
- •What's the difference between async and defer?
- •What is critical CSS and how do you inline it?
- •How do web fonts affect rendering?
Common mistakes
- •Forgetting CSS is render-blocking — focusing only on JS.
- •Putting synchronous scripts in the head without defer/async.
- •Using @import in CSS (serial, blocking downloads).
- •Not addressing font loading (FOIT).
Performance considerations
- •Render-blocking resources are the primary determinant of FCP/LCP. Inlining critical CSS and deferring JS can dramatically cut time-to-first-paint; the rest (minify, compress, CDN, preconnect) reduces the bytes and round-trips that make blocking worse.
Edge cases
- •A small but slow-to-fetch CSS file still blocks paint.
- •async script order being non-deterministic and breaking dependencies.
- •Above-the-fold content depending on a large stylesheet.
- •Third-party scripts blocking the main thread.
Real-world examples
- •Lighthouse's 'Eliminate render-blocking resources' audit.
- •Inlining critical CSS and adding defer to scripts to fix a slow FCP.