What are reflows and repaints?
PerformanceThe short answer
A reflow (also called layout) happens when the browser recalculates the position and size of elements on the page. A repaint happens when the browser redraws elements without changing their layout (like changing a color). Reflows are expensive because they trigger layout recalculation for part or all of the page. Repaints are cheaper but still cost time. Minimizing both is key to smooth performance.
How the browser renders a page
To understand reflows and repaints, you need to know the rendering pipeline:
- Parse HTML → Build the DOM tree
- Parse CSS → Build the CSSOM tree
- Combine → Create the render tree (DOM + styles)
- Layout (reflow) → Calculate position and size of every element
- Paint (repaint) → Fill in pixels (colors, borders, shadows, text)
- Composite → Combine painted layers and display on screen
When something changes on the page, the browser needs to redo some of these steps. How many steps depend on what changed.
What triggers a reflow
A reflow happens when the geometry of the page changes — anything that affects size or position:
- Adding or removing DOM elements
- Changing element size (width, height, padding, margin, border)
- Changing font size
- Changing window size (resize event)
- Reading layout properties like
offsetHeight,clientWidth,getBoundingClientRect() - Changing
display,position, orfloat
// Each of these triggers a reflowelement.style.width = '200px';element.style.margin = '10px';element.classList.add('expanded');document.body.appendChild(newElement);// Even reading layout values triggers a reflow// because the browser must calculate up-to-date valuesconst height = element.offsetHeight;The expensive part is that a reflow on one element can cascade — it might affect the size and position of its parent, siblings, and children.
What triggers a repaint
A repaint happens when the visual appearance changes without affecting layout:
- Changing
color,background-color - Changing
visibility(but notdisplay) - Changing
box-shadow,border-radius - Changing
outline
// These trigger a repaint but NOT a reflowelement.style.color = 'red';element.style.backgroundColor = 'blue';element.style.visibility = 'hidden';A reflow always triggers a repaint (because if the layout changes, it needs to be redrawn), but a repaint does not always trigger a reflow.
How to minimize reflows
1. Batch DOM changes
// Bad — triggers reflow on every changeelement.style.width = '100px';element.style.height = '200px';element.style.margin = '10px';// Good — use a class to batch changeselement.classList.add('resized');// All three changes happen in one reflow2. Avoid reading and writing layout properties in a loop
// Bad — forces a reflow on every iterationfor (let i = 0; i < items.length; i++) { items[i].style.width = box.offsetWidth + 'px'; // offsetWidth forces the browser to recalculate layout each time}// Good — read once, then writeconst width = box.offsetWidth;for (let i = 0; i < items.length; i++) { items[i].style.width = width + 'px';}This pattern of alternating reads and writes is called layout thrashing. The browser cannot batch the changes because each read forces it to recalculate.
3. Use CSS transforms instead of layout properties for animations
/* Bad — triggers reflow on every frame */.animate { transition: left 0.3s, top 0.3s;}/* Good — only triggers composite, no reflow or repaint */.animate { transition: transform 0.3s;}transform and opacity changes are handled by the compositor thread and do not trigger reflow or repaint. This is why transform: translateX(100px) is much smoother than changing left: 100px.
4. Use documentFragment for multiple DOM additions
const fragment = document.createDocumentFragment();for (let i = 0; i < 100; i++) { const li = document.createElement('li'); li.textContent = `Item ${i}`; fragment.appendChild(li);}// One reflow instead of 100list.appendChild(fragment);5. Take elements out of the flow for heavy changes
If you need to make many changes to an element, take it out of the document flow, make changes, then put it back:
element.style.display = 'none'; // triggers one reflow// ... make many changes ...element.style.display = 'block'; // triggers one reflow// Two reflows instead of manyCommon Pitfalls
A very common performance mistake is layout thrashing — reading a layout property and then immediately writing to the DOM in a loop. Each read forces the browser to synchronously recalculate layout. If you see jank or stuttering during animations or scroll handlers, layout thrashing is often the cause.
Interview Tip
When explaining reflows and repaints, draw the rendering pipeline (DOM → CSSOM → Render Tree → Layout → Paint → Composite) and show which steps are affected by each. Then give practical optimization tips — batch DOM changes, avoid layout thrashing, use transforms for animations. This shows you understand not just the concept but how to apply it.
Why interviewers ask this
This is an advanced performance question that shows deep understanding of how browsers work. Interviewers want to see if you can explain the rendering pipeline, identify what causes expensive reflows, and optimize code to avoid them. This knowledge directly impacts the user experience — jank-free animations and smooth scrolling depend on minimizing reflows.