Tags: web-dev concept

The Rendering Pipeline

Date: 2026-08-16


Style, layout, paint, composite — in that order, every frame. Which stage your change enters at decides whether it costs microseconds or milliseconds, and that single fact explains nearly all front-end performance advice.


What it is

The rendering pipeline is the fixed sequence the browser runs to turn the DOM and CSS into pixels on screen.

1  STYLE       which CSS rules apply to which element, and what the
               computed value of every property is

2  LAYOUT      where each box sits and how big it is — geometry.
               Also called reflow

3  PAINT       filling in pixels: colours, text, borders, shadows,
               into one or more layers

4  COMPOSITE   assembling the layers in the right order and putting
               them on screen. Runs on the GPU

Each stage feeds the next. Entering at an earlier stage forces every stage after it.

The cost hierarchy

This is the payoff, and it’s worth memorising:

ChangeTriggersCost
width, height, top, margin, font-sizeLayout → Paint → CompositeExpensive
background-color, color, box-shadow, border-radiusPaint → CompositeModerate
transform, opacityComposite onlyCheap

In plain terms: moving something with left: 20px makes the browser recalculate where everything is, redraw it, then reassemble it. Moving the same thing with transform: translateX(20px) only changes how an already-drawn layer is positioned when it’s pasted onto the screen. Same visual result, an order of magnitude apart.

This is the entire reason animation advice says to stick to transform and opacity — see Animation Performance.

Layout is the expensive one

Layout is expensive because it’s interdependent: changing one element’s size can change the position of everything after it, and its parent, and its parent’s siblings. The browser often can’t recompute one box in isolation.

Two things make it worse:

  • Deep or wide trees. More nodes, more geometry to solve
  • Layout thrashing — reading a geometric property after writing one, in a loop, forcing a synchronous recalculation each time. See Reflow and Repaint for the read/write batching fix

The frame budget

At 60Hz the browser has 16.7 milliseconds to produce a frame. Everything — JavaScript, style, layout, paint, composite — has to fit.

16.7ms budget

  JS        style    layout    paint    composite
 ├────────┤├──────┤├────────┤├───────┤├─────────┤
      ↑
   yours. everything else is the browser's, and it needs most of it

Realistically your JavaScript has around 8–10ms. Exceed the budget and a frame is dropped, which the user sees as jank. On a 120Hz display the budget halves.

This is also why the main thread matters so much: JavaScript and rendering share it, so a long task doesn’t slow rendering down — it stops it entirely. See Long Tasks and Blocking.

Where it connects

Practical

  • Animate transform and opacity only. Anything else animates through layout or paint every frame
  • Batch DOM reads and writes rather than interleaving them
  • Reserve space for images and late-loading content so layout doesn’t run after paint
  • Use DevTools’ Performance panel and read the colour bands — purple is layout, green is paint. If you see purple during an animation, something is entering the pipeline too early
  • will-change sparingly. It promotes an element to its own layer in advance, which helps once and costs memory if applied broadly