Loading...
Loading...
The complete 5-stage path from URL to pixels — for SDE-2 frontend interviews.
Module 2 · Browser Rendering Pipeline
The complete 5-stage path from URL to pixels: Parse (DOM & CSSOM), Style (render tree), Layout (reflow), Paint, and Composite — plus what triggers each stage and how to optimize for Web Vitals.
From URL to pixels in five stages: Parse (DOM & CSSOM), Style (render tree), Layout, Paint, and Composite. Learn what triggers each stage, which CSS properties are cheap vs expensive, and how to avoid forced reflow and layout thrashing.
Once HTML and CSS reach the browser, a fixed pipeline converts bytes into pixels on screen. Every frontend performance decision — animations, layout changes, lazy loading — maps to one of these five stages.
This module is built for SDE-2 frontend interviews: you will learn not just the stages, but which CSS properties trigger layout vs paint vs composite-only updates, how forced reflow happens, and how LCP, INP, and CLS connect to the pipeline.
By the end, you will be able to explain the critical rendering path end-to-end, diagnose layout thrashing in DevTools, and recommend animation and DOM strategies that stay on the compositor thread.
The Concepts tab walks through each pipeline stage with examples; the Interview tab covers reflow vs repaint, GPU layers, and how to fix CLS and INP issues rooted in layout work.
Every UI jank, layout shift, and slow animation traces back to this pipeline. SDE-2 frontend interviews expect you to explain reflow vs repaint vs composite, diagnose layout thrashing, and connect pipeline stages to LCP, INP, and CLS. Optimizing animations to use transform and opacity only is a direct application of this knowledge.
For SDE-2 Frontend Engineer roles — the complete critical rendering path inside the browser.
After the network delivers HTML and CSS, the browser runs a fixed pipeline to turn bytes into pixels. Unlike server rendering strategies (CSR, SSR), this pipeline runs on every page load and every DOM update. Understanding it is essential for performance debugging and frontend system design interviews.
Interactive · Browser rendering pipeline
Parse: HTML → DOM, CSS → CSSOM
The parser tokenizes bytes into nodes. CSS blocks render until the CSSOM is complete — that is why render-blocking stylesheets delay first paint.
🌳 DOM + CSSOM trees built
Interview framing
HTML bytes become a DOM tree; CSS bytes become a CSSOM tree.
The parser converts raw bytes into structured trees the rest of the pipeline can use. HTML and CSS are parsed in parallel, but CSS blocks rendering until the CSSOM is ready.
HTML Bytes → Decode → Tokenize → DOM Tree CSS Bytes → Decode → Tokenize → CSSOM Tree
Key details
DOM construction
CSSOM construction
DOM + CSSOM merge into a render tree of visible elements with computed styles.
The render tree contains only elements that will be painted. Each node stores the element plus its final computed style— not the original CSS source.
DOM + CSSOM → Render Tree (visible elements only)
Excluded from render tree
display: none — not painted, not in layoutIncluded in render tree
visibility: hidden — invisible but still occupy space in layoutStyle computation steps
The browser calculates x, y, width, and height for every render tree node.
Layout (also called reflow) determines where every box sits on screen. It starts at the root and walks down the tree. Window resize triggers a full layout recalculation — expensive at O(n) for large DOMs.
Render Tree → Layout Tree (x, y, width, height)
Why layout is expensive
top or width causes jank.Layout results are rasterized into paint layers — backgrounds, text, borders, images.
Paint converts vector descriptions (boxes, fonts, borders) into bitmaps. Output is split into layers so the browser can repaint only what changed instead of the full page.
Layout Tree → Paint Layers (backgrounds, borders, text, images)
Paint layers are merged on the GPU into the final frame on screen.
The compositor thread sends layers to the GPU. This is the fastest stage — only layer merging, no layout or paint. Animating transform and opacity runs here at 60fps.
Paint Layers → GPU → Final Bitmap on Screen
Promoted to own compositor layer
Alpha blending
Critical for interviews — know the cost of every DOM and CSS change.
Not every change runs the full pipeline. The browser skips stages when possible. Interview answers should name which stages re-run and why.
| Operation | Triggers | Cost | Example |
|---|---|---|---|
| Add/remove DOM element | Layout → Paint → Composite | Expensive | removeChild() |
| Change width, height, top, left | Layout → Paint → Composite | Expensive | Moving with top/left |
| Change margin, padding, font-size | Layout → Paint → Composite | Expensive | Text resize |
| Change color, background, border-color | Paint → Composite | Medium | Color fade |
| Change visibility | Paint → Composite | Medium | Hide without removing |
| Change transform, opacity, filter | Composite only | Cheap | Smooth 60fps animation |
| Read offsetTop, getBoundingClientRect() | Forces synchronous Layout | Blocks thread | Layout thrashing in loops |
Which properties to use for animations and which to avoid.
Composite-only (best for animations)
transformmove/scale/rotate without layoutopacityfade without affecting layoutfilterblur, brightness, contrastwill-changehint browser for upcoming changesPaint-only (medium cost)
colortext color changebackground-colorfill colorborder-colorborder colorvisibilityhide but keep spacebox-shadowshadow effectsLayout + paint (expensive)
width, heightgeometry changesmargin, paddingspacing changestop/left/right/bottomposition changesdisplayblock → flex reflows childrenfont-size, line-heighttext reflowThe performance bug that blocks the main thread in tight read/write loops.
The browser batches layout work for efficiency. When JavaScript reads a geometric property after writing styles, it must flush pending layout immediately — a forced synchronous reflow.
Bad — write then read in a loop
for (let i = 0; i < elements.length; i++) { elements[i].style.width = (i * 10) + 'px'; // WRITE console.log(elements[i].offsetWidth); // READ → forced reflow }
Good — batch reads, then batch writes
const widths = []; for (let i = 0; i < elements.length; i++) { widths[i] = elements[i].offsetWidth; // read once } for (let i = 0; i < elements.length; i++) { elements[i].style.width = widths[i] + 'px'; // write once }
Chrome DevTools rule
Map Core Web Vitals to pipeline stages for interview answers.
Pipeline stage: Paint (and upstream Parse/Layout)
Optimize: Reduce critical rendering path, SSR/SSG for faster HTML, optimize and preload LCP image, avoid render-blocking CSS/JS
Pipeline stage: Across pipeline + main-thread JS
Optimize: Keep event handlers short, defer non-urgent work, avoid long tasks that delay paint after interaction
Pipeline stage: Layout
Optimize: Reserve space with width/height or aspect-ratio on images and embeds, never inject content above existing viewport content
Common interview questions about the browser rendering pipeline.