Critical CSS Approaches
Inline above-the-fold CSS, extract critical rules, and avoid shipping megabyte stylesheets on first paint.
- performance
- critical-css
- css
- fcp
- lcp
CSS is render-blocking by default. A 400KB stylesheet on the critical path delays first paint even if most rules apply to settings pages the user never opens. Critical CSS techniques ship only what first paint needs ASAP — with real maintenance cost.
Docs: web.dev extract critical CSS, Critical rendering path.
Approaches ranked by pragmatism
1. Don’t ship unused CSS (best default)
Framework-scoped CSS, CSS modules, Tailwind purge/content scanning, dead code elimination. Smaller full sheet often beats a fragile critical pipeline.
2. Route-split CSS
Each route imports its own CSS so the home page doesn’t download admin grids. Bundlers emit separate CSS files per async chunk.
// route module pulls its styles
import './settings.css';
3. Inline true critical CSS
<head>
<style>
/* only above-the-fold rules for this template */
header{...} .hero{...}
</style>
<link rel="preload" href="/app.full.css" as="style" onload="this.onload=null;this.rel='stylesheet'" />
<noscript><link rel="stylesheet" href="/app.full.css" /></noscript>
</head>
Generators (Critters, critical, Penthouse) extract selectors for a viewport. Caveats: dynamic class names, responsive breakpoints, and auth-dependent markup break extraction.
4. Media tricks (legacy)
media="print" onload="this.media='all'" is an old async CSS pattern; preload + onload is clearer today. Still test FOUC.
What belongs in critical set
| Include | Exclude |
|---|---|
| Header, nav, hero | Modals, footers below fold |
| Core typography | Admin-only components |
| First viewport layout | Third-party widget CSS |
Keep inlined CSS small (often < 14KB compressed as a rule of thumb for early round trips — validate for your HTTP version).
FOUC and hydration
Async full CSS can flash unstyled controls if critical set is incomplete. Prefer slightly more critical CSS over flashy FOUC. SSR frameworks that stream CSS per component reduce need for manual critical extraction.
Measurement
- Coverage tool in DevTools — red unused rules on load.
- Filmstrip FCP/LCP before/after.
- Ensure LCP element styles aren’t in the deferred sheet.
Interview out-loud
“Critical CSS means getting first-viewport styles to the browser without a huge render-blocking file. I prefer unused-CSS elimination and route splitting first; inline extraction second for marketing pages. Measure Coverage and FCP, watch FOUC.”
How this shows up in interviews
Be ready to define the metric or technique in one sentence, name one measurement approach (DevTools panel, web-vitals, or headers), and cite a concrete fix you would try first. Walk through a before/after: what the waterfall or flame chart showed, what you changed, and which percentile moved. Mention a tradeoff (complexity, caching correctness, or third-party business constraints) so the answer doesn’t sound like a blog checklist.
Production guardrails
Ship behind a flag when the change is risky, watch field p75 for the affected template for at least a few days, and keep a rollback path. Pair lab verification (throttled Performance/Network) with RUM so you don’t celebrate a Lighthouse-only win. Document the owner of any ongoing budget or third-party exception.
Related
Further depth
Teams often under-invest in this topic until an incident or CWV regression. Schedule a one-hour drill: reproduce the failure mode in DevTools, list the top three mitigations for your stack, and file tickets with owners. Revisit after the next major feature that touches networking, rendering, auth, or third parties — those are the moments regressions land. Keep primary documentation links in the runbook so on-call is not searching chat history at 2am.
Concrete artifacts to leave behind: a short architecture note, a CI assertion or header snapshot, and a dashboard panel (lab or field) that would have caught the last bug. Teaching the rest of the team the mental model matters as much as the one-line fix.
Further reading
Related guides
- Code Splitting StrategiesRoute, component, and vendor splits: dynamic import(), magic comments, and avoiding over-splitting waterfalls.
- Image Optimization FormatsAVIF, WebP, JPEG, PNG: choose formats, quality, and tooling so LCP images stay sharp and small.
- LCP Optimization TacticsDeep tactics for Largest Contentful Paint — discovery, priority, bytes, server delay, and render delay — beyond the CWV overview.
- Network Waterfall ReadingRead request waterfalls: critical path chains, priority, blocking, and how to shorten discovery delays.
- Preconnect and DNS PrefetchWarm critical third-party origins with preconnect; use dns-prefetch lightly; don’t shotgun hints.