simoong·blog

Reflow and Repaint: A Complete Guide to Slow Web

Reflow vs. Repaint — Factors That Really Impact Browser Rendering Performance

image

Recently, while reviewing rendering performance, I came across the distinction between Reflow and Repaint.

While these two terms often appear in web performance issues, there aren't many articles that clearly explain the difference between them.

These two terms inadvertently incur rendering costs when using React, RealGrid, or general DOM manipulation.

--

💡 What are Reflow and Repaint?

When a browser draws a page, it doesn't simply interpret HTML.
DOM → CSSOM → Render Tree is created, and Layout and Paint are performed based on this.

If any changes occur during this process, the browser must recalculate.

Terminology Description
Reflow (Layout) Layout recalculation that occurs when an element's size or position changes.
Repaint Repaint that occurs when only visual styles, such as color or background, change.

In short, Reflow occurs when the structure changes, and Repaint occurs when the color changes.


🧩 For example:

<div id="box" style="width: 100px; height: 100px; background: red"></div>
<script>
    const box = document.getElementById('box')
 
    // 1️⃣ Reflow occurs
    box.style.width = '200px' // Size or position change → Layout recalculation
 
    // 2️⃣ Repaint occurs
    box.style.backgroundColor = 'blue' // Color change → Only repaint
</script>

In the above code, changing width causes both Reflow → Repaint.

However, changing only backgroundColor causes only Repaint.

Reflow is much more expensive than paint.

The browser must recalculate the layout of not only the changed element, but also all affected child and parent elements.


⚙️ Performance Impact

Reflow occurs more easily than you might think.

Here are some common situations that cause reflow:

Cause Explanation
DOM size changes width, height, margin, padding, font-size, etc.
DOM structure changes Adding/deleting nodes (appendChild, removeChild)
Position changes top, left, position, display, etc.
Window size changes resize event
Scroll/overflow changes Layout reordering upon scrolling
Accessing offset, client, and scroll properties Forces the browser to compute the latest layout

If these changes become frequent, the browser must continuously repeat the Layout → Paint → Composite stages.


🔬 Common Practice Examples

1️⃣ Repeated DOM Manipulation

// ❌ Inefficient Method
for (let i = 0; i < 1000; i++) {
    const el = document.createElement('div')
    el.textContent = i
    document.body.appendChild(el) // Causes a reflow every time
}

This code causes 1000 reflows.

Because the browser recalculates the layout every time an element is appended.

Solution: Add all at once using DocumentFragment

const frag = document.createDocumentFragment()
for (let i = 0; i < 1000; i++) {
    const el = document.createElement('div')
    el.textContent = i
    frag.appendChild(el)
}
document.body.appendChild(frag) // Reflow only once

2️⃣ Continuously changing style properties

// ❌ Multiple reflows
box.style.width = '200px'
box.style.height = '200px'
box.style.margin = '20px'

Solution: Use classList or CSS text Bundling

box.classList.add('expanded')
// or
box.style.cssText = 'width:200px;height:200px;margin:20px;'

This allows the browser to refresh the rendering in one go.


3️⃣ Forced Reflow

This is something you really need to be careful about.

If the code that reads layout information and the code that modifies it are mixed, as shown below, the browser will force a reflow.

el.style.width = '200px'
console.log(el.offsetWidth) // 💥 Forced Reflow

Because when reading offsetWidth, the browser must ensure an "up-to-date layout,"

it will re-run all the calculations.

In other words, the "read-write-read" pattern is the enemy of performance.


🧠 Practical Optimization Tips

Situation Recommended Method
When multiple elements need to be modified Process DocumentFragment / display:none and then make batch changes
When many style changes are required Group and replace with a CSS class
Scroll and resize events Control with Debounce / Throttle
Animation Focus on transform and opacity properties (no reflow)
Avoiding forced reflow Minimize access to offset and scroll properties

Reflow can be reduced, but not completely eliminated.
However, understanding "when and why" it occurs can help prevent most performance issues.


⚡ CSS Tips for Avoiding Reflow

  • transform and opacity can be animated without reflow.
  • position: absolute or fixed can be used to reduce the scope of influence.
  • will-change provides optimization hints to the browser in advance.
  • contain property ensures layout independence of child elements (CSS Containment).

You can check these properties in Chrome DevTools under the Rendering tab → “Paint flashing” option.


📊 Summary

| Category | Reflow | Repaint |
|------|--------|----------| | Trigger | When layout structure changes | When visual properties change |
| Cost | High | Medium |
| Trigger | Width, height, position, font-size, etc. | Color, background, etc. |
| Optimization Point | Minimize layout changes | Reduce unnecessary paints |


💬 In Conclusion

Reflow and repaint are invisible, but they directly impact browser performance.

Even if you use a virtual DOM like React or Vue, reflow is unavoidable when the real DOM update occurs at the final stage.

In other words, the virtual DOM is merely a "reflow reduction strategy," not a technology that eliminates it.

Understanding this difference and writing code accordingly will allow you to create much smoother and more efficient UIs.

Browsers are smarter than you think, but even small mistakes can be costly.
When writing code, always ask yourself, "Will this line cause a reflow?"

--

#Reflow #Repaint #BrowserRendering #RenderingPerformance #CSSPerformance #JavaScriptPerformance #WebOptimization #FrontEndPerformance #ReflowOptimization #VirtualDOM