Introduction
CSS is render-blocking by default — the browser won't paint anything until all CSS is downloaded and parsed. Critical CSS extraction identifies styles needed for the initial viewport, inlines them, and defers the rest.
This technique can improve First Contentful Paint by 1-3 seconds on slower connections, making it one of the highest-impact CSS optimizations.
This guide covers automated extraction tools and implementation patterns for modern frameworks.
Key Concepts
The Inline + Defer Pattern
<head>
<style>/* Only above-the-fold styles */
body { margin: 0; font-family: system-ui; }
.header { display: flex; padding: 1rem; }
.hero { min-height: 60vh; display: grid; place-items: center; }
</style>
<link rel="preload" href="/styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="/styles.css"></noscript>
</head>
Practical Examples
1. Critters Plugin
// webpack
const Critters = require('critters-webpack-plugin');
module.exports = { plugins: [new Critters({ preload: 'swap', inlineFonts: false })] };
// Vite
import critters from 'vite-plugin-critters';
export default defineConfig({ plugins: [critters()] });
2. PurgeCSS
// postcss.config.js
module.exports = {
plugins: [
require('@fullhuman/postcss-purgecss')({
content: ['./src/**/*.{html,tsx,jsx}'],
safelist: ['active', 'open', /^data-/],
}),
],
};
3. Next.js Automatic CSS Optimization
module.exports = { experimental: { optimizeCss: true } };
Best Practices
- ✅ Automate critical CSS extraction in your build pipeline
- ✅ Keep critical CSS under 14KB (fits in first TCP round-trip)
- ✅ Use CSS Modules or CSS-in-JS for per-component splitting
- ✅ Run PurgeCSS to remove unused styles
- ❌ Don't manually maintain critical CSS — it will drift
- ❌ Don't inline your entire stylesheet
Common Pitfalls
- 🚫 Inlining too much CSS — exceeding 14KB can slow initial load
- 🚫 Breaking interactive states like :hover and :focus
- 🚫 Not testing on real pages — different pages need different critical CSS
- 🚫 Forgetting the noscript fallback