Summary
The browser renders a frame by running up to four stages: Style (match CSS rules), Layout/reflow (compute geometry), Paint (record draw calls), and Composite (GPU layer merge). Triggering Layout is the most expensive path; CSS properties like `transform` and `opacity` skip it entirely and run on the compositor thread, costing far less than a full reflow.
Jump to the interview angleWhat each stage does
- 1
Style
The browser matches every CSS rule against the DOM and computes the final computed style for each element. Triggered on any class or attribute change that alters applied rules.
- 2
Layout (reflow)
Geometry is computed: position, width, height, and margin for every affected element and its descendants. Changing
width,height,top,margin, orpaddingstarts here. Reflow is the most expensive stage on a large DOM. - 3
Paint
The browser records draw calls (fills, strokes, shadows, text) into a display list per layer. Triggered by color, background, box-shadow, or border changes — but not geometry shifts.
- 4
Composite
The GPU merges painted layers in the correct stacking order and sends the finished frame to the screen.
transformandopacityanimate here without touching the main thread.
CSS property cost by pipeline stage
| Property change | Triggers | Thread | |
|---|---|---|---|
| width / height / margin | Style + Layout + Paint + Composite | Main | |
| color / background-color | Style + Paint + Composite | Main | |
| transform / opacity | Composite only | Compositor (GPU) | |
| box-shadow / border-radius | Style + Paint + Composite | Main |
Layout thrash
Reading a geometry value (offsetWidth, getBoundingClientRect()) after a DOM write forces the browser to flush pending layout synchronously. Inside a loop this multiplies reflow cost by iteration count. Batch all reads before writes, or defer writes to requestAnimationFrame.
Compositor-layer rules of thumb
- Animate `transform` and `opacity` — they skip the main thread entirely.
- Use `will-change: transform` only on elements that will animate; excess layers waste GPU memory.
- Each `will-change` or `transform` creates a stacking context — watch for z-index surprises.
- Profile with Chrome DevTools Performance panel before promoting layers speculatively.
- Avoid animating `top`/`left` with JS; use `translate()` instead to stay on the compositor.
Interview angle
Interviewers test whether you can say which CSS property triggers which stage, explain layout thrash, and fix it. Soundbite: "transform and opacity skip Style, Layout, and Paint — they run on the compositor thread and never block the main thread."
Key terms
- reflow
- Browser recalculating geometry of every affected element; triggered by dimension or position changes.
- layout thrash
- Alternating DOM reads and writes inside a loop, forcing repeated synchronous reflows.
- compositor thread
- GPU-side thread that merges pre-painted layers; runs independently of the main thread.
- will-change
- CSS hint that promotes an element to its own compositor layer before animation starts.
- stacking context
- Isolated z-order subtree created by properties like `opacity < 1`, `transform`, or `isolation: isolate`.