What is the critical rendering path?
Take a moment.
Say your answer out loud or write it down first — retrieval is what makes it stick. Reveal when you're ready.
Short answer
The steps from bytes to pixels: parse HTML into the DOM, parse CSS into the CSSOM, combine them into the render tree, lay out geometry, then paint and composite layers. Anything blocking those steps — synchronous scripts, slow stylesheets — delays first paint, so the whole performance playbook is about unblocking this path.
Detailed explanation
When navigation commits, the browser streams HTML and tokenizes it into the DOM incrementally — but a classic <script> pauses parsing until the script downloads and executes (it might document.write), and stylesheets block rendering until the CSSOM is built (painting unstyled content would flash). So the path is: DOM construction and CSSOM construction (parallel, except scripts wait for pending CSS), then the render tree (visible DOM nodes + their computed styles — display:none subtrees are excluded), then layout (also called reflow: each node's exact position and size, relative to the viewport), then paint (fill pixels into layers: text, colors, images, shadows), then compositing (the GPU combines layers, applying transforms and opacity cheaply). DevTools' Performance panel shows exactly these phases per frame. Optimization follows the structure: minimize bytes (minify, compress with Brotli/Gzip), shorten the chain (inline critical CSS, defer non-critical CSS/JS, async or defer scripts), avoid render-blocking surprises (preconnect to origins, preload the hero font/image), and keep runtime updates on the compositor (animate transform/opacity, never width/top). The business metric tied to this path is LCP — when the largest contentful element finishes this journey.
Example
<!-- Unblock the path -->
<head>
<style>/* critical above-the-fold CSS inlined */</style>
<link rel="preload" href="/hero.avif" as="image" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<!-- non-critical CSS loads without blocking -->
<link rel="stylesheet" href="/app.css" media="print" onload="this.media='all'" />
</head>
<body>
<!-- ... -->
<!-- deferred scripts never pause parsing -->
<script src="/app.js" defer></script>
</body>Interview tip
Recite the five stages in order (DOM → CSSOM → render tree → layout → paint/composite), then name what blocks each. One concrete unblocking fix proves it is operational knowledge, not vocabulary.
Common mistakes
- Forgetting stylesheets block rendering while scripts block parsing.
- Putting synchronous third-party scripts in <head>.
- Animating layout properties like width instead of transform.