Mastering the Browser Performance: Reducing Reflows and Repaints

Reflows and repaints are among the most performance-hindering operations in a browser. This article dives into the intricate details of these two phenomena, demonstrates how to detect and reduce them, and presents real-world case studies that have successfully mitigated their impact.

ShareShare

Mastering the Browser Performance: Reducing Reflows and Repaints

Even after optimizing your bundle and API, your application's user interface (UI) may still exhibit lag, stutter, or a heavy feel. This sluggish behavior might not be due to JavaScript but rather the browser itself overworking — recalculating layout and repainting excessively.

These operations are known as reflows and repaints, and they’re some of the most computationally expensive tasks a browser performs. This article elucidates what reflows and repaints are, the conditions that trigger them, how to detect and reduce them, what causes layout thrashing, and best practices gleaned from real-world solutions.

Reflows: The Backdrop

A reflow, also known as a layout, occurs when the browser recalculates the geometry of the webpage. This encompasses the positions of elements, their widths and heights, box models, and stacking order. Modifications to the Document Object Model (DOM) size or position frequently instigate reflows.

Demystifying Repaints

On the other hand, a repaint occurs when parts of the screen are redrawn following a style change. These alterations can include color changes, shadows, and visibility. Although repainting is less costly than a reflow, it still demands significant resources, especially when dealing with large surfaces.

Triggers for Reflows

Several actions can trigger a reflow. These include:

  • The addition or removal of DOM nodes
  • Changes to styles that affect layout (e.g., display, height, margin)
  • Calls to measurement APIs such as offsetHeight and getBoundingClientRect
  • Animation of properties that necessitate layout recalculations

Detecting Reflows and Repaints

To identify reflows and repaints, use Chrome DevTools' Performance tab to record interactions. Look for events like "Recalculate Style", "Layout", "Paint", and "Composite Layers". The Paint Flashing tool in the Rendering panel visualizes repaints.

Furthermore, you can use console.time() to measure the execution time of critical paths. For instance:

console.time("layout");
element.offsetHeight;
console.timeEnd("layout");

The above code times how long it takes to calculate element.offsetHeight.

Techniques to Mitigate Layout Thrashing

Read, then Write

Interleaving reading and writing operations can cause layout thrashing. Consider the following example:

el.style.width = "100px";
const h = el.offsetHeight;
el.style.border = "1px solid red";

In the above code, a write operation (el.style.width = "100px"), followed by a read operation (const h = el.offsetHeight), and then another write operation (el.style.border = "1px solid red") results in reflows.

A better approach is to bundle all read operations before write operations, as shown below:

const h = el.offsetHeight;
el.style.width = "100px";
el.style.border = "1px solid red";

Avoiding Layout-Affecting Animations

Animations that affect layout should be avoided. For instance, instead of animating properties like height, animate properties like transform:

transition: transform 0.3s;

Properties such as transform and opacity are GPU-accelerated and don't necessitate layout recalculations.

Utilizing CSS Containment

CSS Containment can help improve performance in dynamic UIs. It instructs the browser not to reflow beyond the defined boundary:

.card {
  contain: layout paint;
}

Leveraging Virtualization

For large lists, virtualization techniques can be beneficial. They prevent the DOM from growing unbounded, which would otherwise increase the reflow cost for each frame. Libraries like react-window and react-virtual, or using intersection observers, can aid in implementing virtualization.

Anti-Patterns to Avoid

Several practices can exacerbate reflows and repaints. These include:

  • Animating width, height, top, left
  • Reading layout in the middle of an animation
  • Manipulating the DOM inside requestAnimationFrame with layout reads
  • Synchronous style reads in scroll/resize handlers

Conclusion: Don’t Let Layout Be Your Bottleneck

Reflows and repaints are expensive — not just in CPU cycles, but in perceived fluidity. Users perceive them as jank, lag, or dropped frames. Therefore, to ensure a smooth and responsive UI, it is crucial to keep layout operations predictable and contained.

While it is impossible to avoid reflows entirely, with careful planning and good practices, you can certainly prevent them from disrupting your application's performance.

Subscribe for Deep Dives

Get exclusive in-depth technical articles and insights directly to your inbox.

about

Ehsan Hosseini

Ehsan Hosseini

me [at] ehosseini [dot] info

Staff Software Engineer and Tech Lead with a track record of leading high-performing engineering teams and delivering scalable, end-to-end technology solutions. With experience across web, mobile, and backend systems, I help companies make smart architectural decisions, scale efficiently, and align technical strategy with business goals.

© 2025 Ehsan Hosseini. All rights reserved.