Reflow (layout) recalculates element geometry, while repaint redraws visual styles without changing layout geometry. Strong answers also explain paint-heavy visuals, composite-only updates, and why forced reflow causes runtime jank.
Use this JavaScript interview question to rehearse a quick answer, common mistake, follow-up, and production pitfall.
What is the difference between reflow and repaint in browsers?Frontend interview answer
This JavaScript interview question tests whether you can explain Reflow vs repaint: layout thrashing, paint cost, and composite debug, connect it to production trade-offs, and handle common follow-up questions.
- Reflow vs repaint: layout thrashing, paint cost, and composite debug explanation without falling back to memorized docs wording
- Performance and Rendering reasoning, edge cases, and production failure modes
- How you would answer the most likely JavaScript interview follow-up
The core idea
Browsers render in stages. The two most asked stages are:
- Reflow (layout): recalculate element size/position.
- Repaint: redraw pixels (colors, shadows, visibility) without changing geometry.
Reflow is usually more expensive because geometry changes can cascade through large parts of the DOM tree. Paint-only work is not free either when you redraw large areas or heavy visual effects, but it usually skips layout.
Stage | What changes | Typical triggers | Relative cost |
|---|---|---|---|
Reflow (Layout) | Box size/position and document flow | Changing width/height, font-size, DOM insertions/removals | High |
Repaint | Visual appearance only | Changing color/background/visibility/outline | Medium |
Composite | Layer composition on GPU | Transform/opacity updates on isolated layers | Lower (often) |
const box = document.querySelector('.box');
// Repaint only (no geometry change):
box.style.backgroundColor = 'tomato';
// Reflow + repaint (geometry changes):
box.style.width = '320px';
box.style.padding = '24px';
Paint vs composite follow-up
Paint-only changes can still be expensive when they redraw large backgrounds, shadows, filters, or blur effects. Composite-only updates, often with transform or opacity on isolated layers, are usually cheaper because the browser can move existing pixels instead of recalculating layout.
What makes reflow expensive
Layout changes can invalidate measurements of nearby or ancestor elements. On large pages, one geometry change can force the browser to recalculate positions for many nodes.
This becomes visible as scroll jank, delayed input response, and dropped frames during animations.
Forced synchronous reflow (layout thrashing)
A common performance bug: write styles, then immediately read layout metrics, repeatedly in a loop. Reading layout properties after writes can force the browser to flush layout right away.
const items = document.querySelectorAll('.item');
// ❌ Layout thrashing: write -> read in each iteration
for (const item of items) {
item.style.width = item.clientWidth + 10 + 'px'; // read after prior writes
}
// Reads like offsetWidth/clientWidth/getBoundingClientRect
// can trigger forced layout when styles are dirty.
const items2 = document.querySelectorAll('.item');
// ✅ Better: batch reads first, then batch writes
const widths = Array.from(items2, (el) => el.clientWidth);
requestAnimationFrame(() => {
items2.forEach((el, i) => {
el.style.width = widths[i] + 10 + 'px';
});
});
Goal | Preferred tactic | Why it helps |
|---|---|---|
Avoid layout thrash | Batch reads first, then batch writes in | Prevents repeated forced reflow in loops. |
Smooth animations | Animate | Often avoids layout and heavy paint work. |
Limit blast radius | Use CSS | Reduces how far layout invalidation spreads. |
Lower DOM churn | Toggle CSS classes or batch DOM updates (fragments/virtual DOM batching) | Fewer layout/paint cycles per interaction. |
How to diagnose in DevTools
Record a trace in the Performance panel while reproducing jank:
- Look for frequent Layout events and long Paint tasks.
- Correlate long frames with JavaScript that reads layout after style writes.
- Check whether animation steps stay near the 16.7ms/frame budget (60fps target).
.card {
/* isolate layout/paint when appropriate */
contain: layout paint;
}
/* Prefer transform for motion instead of top/left when possible */
.bad-move { top: 20px; left: 20px; }
.good-move { transform: translate(20px, 20px); }
Interview one-liner
Reflow recalculates layout geometry and is generally more expensive; repaint redraws visuals without layout changes. Optimize by minimizing layout invalidations, batching DOM reads/writes, and animating transform/opacity where possible.
Practical scenario
A filter sidebar and analytics dashboard both update card dimensions on every keystroke, causing repeated layout reads and writes that create visible typing lag. Paint-heavy shadows on the cards make the slow frames even more obvious.
Common pitfalls
- Reading
getBoundingClientRect()right after multiple style mutations. - Animating
top/left/widthfor high-frequency transitions. - Using large blur, shadow, or filter effects and assuming “it is only repaint”.
- Ignoring trace data and guessing performance bottlenecks.
Measure before and after in DevTools and RUM. Compare frame times and INP when switching from layout-triggering animations to transform/opacity patterns.
Think of reflow as moving furniture around a room (positions change), while repaint is changing wall color (same layout, new appearance). Moving furniture takes more work.
Use this as one explanation rep, then continue with the JavaScript interview questions cluster or a guided prep path.