Back to Browser Internals
Browser Internals
easy
mid

What is the difference between repaint and reflow in the browser?

Reflow (layout): recalculating element geometry — positions and sizes. Repaint: redrawing pixels (colors, visibility) with geometry unchanged. Reflow is more expensive and triggers a repaint; repaint alone doesn't trigger reflow. ('Rework' isn't a real browser term.) Composite-only props (transform/opacity) skip both.

4 min read·~6 min to think through

("Rework" isn't a browser term — the two real concepts are reflow and repaint, and the third tier is composite.)

Reflow (a.k.a. Layout)

The browser recalculates the geometry of elements — their position and size — and where everything sits in the layout. It's triggered by anything that changes layout:

  • Changing width, height, margin, padding, border, top/left, display, font-size.
  • Adding/removing/resizing DOM nodes.
  • Changing the window size.
  • Reading layout properties (offsetHeight, getBoundingClientRect, scrollTop) — can force a synchronous reflow.

Reflow is expensive — it can cascade: changing one element's size shifts its siblings, its parent, its children. And a reflow always triggers a repaint afterward (new geometry must be redrawn).

Repaint

The browser redraws pixels — but geometry stays the same. Triggered by visual-only changes:

  • color, background-color, visibility, box-shadow, outline, border-color.

A repaint is cheaper than a reflow because the layout is already known — it's "fill in different pixels in the same boxes." A repaint does NOT trigger a reflow.

The hierarchy (cost, cheap → expensive)

ts
Composite only  <  Repaint  <  Reflow (+ repaint)
  • Composite-onlytransform and opacity can be handled by the GPU at the composite stage, skipping both layout and paint. That's why they're the properties you animate.
  • Repaint — paint stage only.
  • Reflow — layout stage, then paint, then composite. The full pipeline.

Optimizing

  • Animate transform/opacity, not top/left/width/height.
  • Batch DOM reads and writes — interleaving them ("read, write, read, write") causes layout thrashing: each read forces a synchronous reflow to get a fresh value. Read all, then write all.
  • Minimize layout-affecting changes in hot paths; change a class once instead of many inline styles.
  • Use will-change sparingly to hint the browser to promote an element to its own layer.

The framing

"Reflow — or layout — is the browser recalculating element geometry: positions and sizes. Repaint is redrawing pixels when geometry hasn't changed — like a color change. Reflow is more expensive and always forces a repaint after it; a repaint alone never causes a reflow. Below both is composite-only: transform and opacity go straight to the GPU, skipping layout and paint entirely — which is why you animate those. The classic mistake that triggers excess reflow is layout thrashing: interleaving DOM reads and writes so each read forces a synchronous layout."

Follow-up questions

  • Why does reading offsetHeight force a reflow?
  • What is layout thrashing and how do you avoid it?
  • Why are transform and opacity cheap to animate?
  • Does a repaint ever trigger a reflow?

Common mistakes

  • Thinking repaint and reflow are the same cost.
  • Animating top/left/width instead of transform.
  • Interleaving DOM reads and writes (layout thrashing).
  • Believing a repaint triggers a reflow (it doesn't).
  • Overusing will-change, which can hurt by creating too many layers.

Performance considerations

  • Reflow is the costliest rendering operation and cascades; repaint is cheaper; composite-only updates are cheapest. Batching reads/writes and animating transform/opacity keeps work off the layout and paint stages — the key to smooth 60fps UIs.

Edge cases

  • Reading a layout property right after a write — forced synchronous reflow.
  • A reflow cascading up and down the tree.
  • Off-screen / display:none elements — changes don't reflow until shown.
  • Animating a layout property at 60fps — jank.

Real-world examples

  • Animating a sidebar with transform: translateX instead of left for jank-free motion.
  • Fixing a slow list by batching all DOM reads before all writes.

Senior engineer discussion

Seniors define reflow as geometry recalculation and repaint as pixel redraw, give the composite < repaint < reflow cost hierarchy, explain layout thrashing and forced synchronous layout, and prescribe transform/opacity animation plus read/write batching.

Related questions