Critical CSS Inlining Guide
What Is Critical CSS?
When a browser loads a page, it must download and parse every linked CSS file before it can render any content. A stylesheet in the <head> blocks rendering — even if 90% of its rules apply to elements below the fold. This delay is visible as a blank white screen, especially on slow connections.
Critical CSS is the subset of styles needed to render the above-the-fold content — everything visible in the viewport on initial load without scrolling. By inlining this CSS directly in the HTML <head> and loading the remaining stylesheet asynchronously, you eliminate the render-blocking delay.
The Render-Blocking Problem
A typical page loads CSS like this:
<head>
<link rel="stylesheet" href="/styles.css">
</head>
The browser timeline looks like:
- Download HTML — wait for network
- Parse HTML, find
<link>— stop rendering - Download
styles.css— wait for network again - Parse CSS, build CSSOM
- Combine with DOM, render first pixel
Steps 2–4 add latency proportional to your CSS file size and network speed. A 200KB stylesheet on a 3G connection adds over one second of blank screen.
How Critical CSS Inlining Works
The optimized approach replaces the blocking link with inline styles and an asynchronous load:
<head>
<style>
/* Critical CSS: only above-the-fold rules */
body { font-family: system-ui, sans-serif; margin: 0; }
.hero { background: #1e1b4b; color: white; padding: 4rem 2rem; }
.nav { display: flex; justify-content: space-between; padding: 1rem; }
</style>
<link rel="preload" href="/styles.css" as="style"
onload="this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="/styles.css"></noscript>
</head>
Now the browser:
- Downloads HTML
- Parses inline
<style>— renders first pixel immediately - Preloads
styles.cssin the background - Applies full stylesheet when ready — no visible flash if critical CSS was accurate
Extracting Critical CSS
Manual extraction is impractical for real projects. Use one of these tools:
| Tool | How It Works | Best For |
|---|---|---|
| Critical | Headless browser renders the page, captures used CSS | Static sites, SSG builds |
| Penthouse | Opens URL at specific viewport, extracts matching rules | Multi-viewport extraction |
| critters | Webpack plugin, integrates into build pipeline | Nuxt, Next.js, Vite projects |
For Nuxt projects, the nuxt-critical module automates extraction during generate:
npm install nuxt-critical
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['nuxt-critical'],
})
It extracts critical CSS per route during SSG and inlines it automatically.
Avoiding the Flash of Unstyled Content
If your critical CSS misses rules for above-the-fold elements, users see a brief flash of unstyled content (FOUC) before the full stylesheet loads. To minimize this:
- Extract critical CSS at the most common viewport (1366×768 or 1440×900).
- Include base typography —
body,h1–h6,p,a. - Include layout containers visible without scrolling.
- Include any above-the-fold images or backgrounds referenced in CSS.
A good rule of thumb: if an element occupies space above the fold, its layout and typography styles belong in critical CSS.
Measuring the Impact
Use Lighthouse or Chrome DevTools to measure First Contentful Paint (FCP) before and after inlining:
npx lighthouse https://your-site.com --view --output=html
Typical improvements:
| Metric | Before Inlining | After Inlining |
|---|---|---|
| FCP | 2.4s | 0.9s |
| Render-blocking resources | 2 CSS files | 0 |
| Largest Contentful Paint | 3.1s | 1.8s |
Results vary by site, but FCP improvements of 40–60% are common when moving from a single large blocking stylesheet to critical CSS inlining.
Limitations and Trade-offs
- HTML size increases — inline CSS adds kilobytes to every HTML response and cannot be cached separately. Keep critical CSS under 14KB (the typical TCP window size) for maximum benefit.
- Maintenance burden — critical CSS must be re-extracted when above-the-fold design changes. Automate this in your build pipeline.
- Not needed for HTTP/2 multiplexed small files — if your architecture already splits CSS into many small, cached chunks, the render-blocking delay is minimal and inlining provides less benefit.
Key Takeaways
- Critical CSS is the minimum CSS needed to render above-the-fold content.
- Inlining critical CSS eliminates render-blocking stylesheet delays.
- Load remaining CSS asynchronously via
rel="preload"with a stylesheet fallback. - Automate extraction with tools like Critical, Penthouse, or nuxt-critical.
- Keep inline critical CSS under 14KB to stay within the initial TCP window.
- Re-extract critical CSS whenever your design changes — integrate into your build pipeline.
Try It Yourself
Shrink your CSS payload by minifying your stylesheets with the CSS Minifier.