Browser Rendering Pipeline
From bytes to pixels — parse, style, layout, paint, composite — and how your JS/CSS kicks each stage.
- browser
- rendering
- performance
When you poke the DOM or CSS, the browser doesn’t “just redraw.” It runs a pipeline. Knowing which stage you invalidated explains jank, CLS, and why transform animations feel cheaper than animating top.
The happy path
Bytes → HTML parse → DOM
→ CSS parse → CSSOM
→ Render tree
→ Layout (reflow)
→ Paint
→ Composite → pixels
JS can interleave at almost any time. Read a geometry property (offsetHeight, getBoundingClientRect) while styles are dirty and the browser may force layout right now — the classic layout thrash in a loop.
Stage cheat sheet
| Stage | What it decides | Common triggers |
|---|---|---|
| Style | Computed styles | Class/style changes, matching selectors |
| Layout | Geometry | Width, height, top/left, fonts, content size |
| Paint | Pixels inside layers | Color, shadows, borders, images |
| Composite | Layer glue + GPU-friendly bits | transform, opacity (often) |
Animating transform / opacity can stay on the compositor when layers are set up well. Animating layout properties pays layout + paint more often.
Critical path of first load
- Get HTML (TTFB matters for LCP).
- CSS is render-affecting — large blocking CSS delays first paint.
- Classic
<script>withoutdefer/async/type=moduleblocks parse. - Fonts can block or swap text depending on
font-displayand fallback metrics (CLS risk).
This is the same story as Core Web Vitals, from the browser’s side of the table.
Practical rules
- Batch DOM writes; don’t interleave write/read/write/read in a loop.
- Animate compositor-friendly properties when you can.
- Virtualize long lists — thousands of nodes tax style/layout/paint.
- Measure: Performance panel → see long Recalculate Style / Layout / Paint.
- For responsiveness, long tasks on the main thread delay INP (handlers can’t run; frames can’t paint).
Interview one-liner
“HTML/CSS build DOM and CSSOM, then render tree, layout, paint, composite. JS that reads geometry can force sync layout. Compositor properties avoid layout for many animations. Long tasks block input and paint.”
Further reading
- Rendering performance — web.dev
- Critical rendering path — MDN / web performance
- CSS triggers (community reference for which props dirty which stages)
Related
Related guides
- Compositor LayersWhen browsers promote layers, why transform/opacity animate cheaply, and layer explosion costs.
- Main Thread vs Compositor ThreadWhat runs on the main thread vs compositor, why scroll can be smooth while clicks feel dead, and fix strategies.
- BFCache Back Forward CacheHow the back/forward cache freezes pages for instant history nav, what blocks it, and how to restore state safely.
- Browser DevTools Network PanelRead waterfalls, timing phases, headers, throttling, and initiator chains in the Network panel like a production debugger.
- Browser DevTools Performance PanelRecord main-thread timelines: long tasks, style/layout/paint, frames, and how to turn flame charts into INP fixes.