Critical CSS
By default, a browser blocks rendering of the entire page until every linked stylesheet in the
<head> has been fetched and parsed — even if that stylesheet only affects content far below the fold. Critical CSS is the practice of identifying the minimal set of styles needed to render what's immediately visible when the page loads, inlining just that into the <head>, and loading everything else asynchronously so it never blocks the initial paint.The problem it solves
HTML
<!-- Without critical CSS: the browser can't paint ANYTHING
until styles.css (all of it) has downloaded and parsed -->
<head>
<link rel="stylesheet" href="/styles.css">
</head>If
styles.css is large — or is on a slow connection — the user sees a blank white page for longer than necessary, even though the styles needed for the hero section at the top of the page might be a tiny fraction of that file.The pattern
HTML
<head>
<!-- 1. Inline the minimal CSS for above-the-fold content directly -->
<style>
body { margin: 0; font-family: system-ui, sans-serif; }
.hero { display: flex; align-items: center; min-height: 70vh; }
.hero h1 { font-size: 2.5rem; color: #111; }
</style>
<!-- 2. Load the full stylesheet without blocking rendering -->
<link
rel="stylesheet"
href="/styles.css"
media="print"
onload="this.media='all'"
/>
<noscript><link rel="stylesheet" href="/styles.css" /></noscript>
</head>The
media="print" trick is a well-known technique: the browser still fetches the stylesheet (so it's ready quickly), but because it claims to apply only to print media, it doesn't block rendering of the screen document. Once it finishes loading, the inline onload handler flips media to all, applying the full stylesheet. The <noscript> fallback covers clients with JavaScript disabled.Why this improves perceived load speed
First paint happens sooner — the browser has everything it needs to render the visible viewport the moment the HTML and the small inline
<style>block arrive, without waiting on a separate network round-trip for a full stylesheet.Largest Contentful Paint (LCP) improves — LCP measures when the largest visible element (often a hero image or heading) finishes rendering, and that can only happen once its styles are available; critical CSS removes the render-blocking delay for exactly that content.
The rest of the page loads in the background — non-critical styles (footer, below-the-fold sections, rarely-seen states) load asynchronously without holding up what the user sees first.
Automating extraction
Hand-picking critical styles doesn't scale past a small site, so most real setups use tooling that renders the page (via a headless browser) and automatically determines which CSS rules actually apply to elements in the initial viewport — tools like
critical or critters are common examples, often wired into a build step or framework plugin.This isn't free — it's a real trade-off
Critical CSS adds meaningful build complexity: a tool has to analyze rendered output (per page template, since different pages can have different above-the-fold content), the inlined CSS has to be regenerated whenever a design changes, and the inline/async-load split adds a moving part to your deployment pipeline that has to keep working correctly. For a small site with an already-small stylesheet, the gain may not be worth that added maintenance surface — measure your actual render-blocking delay first.
Many meta-frameworks already do some of this for you
Frameworks with built-in CSS extraction (including some configurations of Next.js) can automatically inline per-page critical styles as part of the build, without a separate third-party tool. Check what your framework already does before adding a dedicated critical-CSS pipeline on top.