Reflow and Repaint
To transform raw code into vibrant pixels on a screen, browsers execute a sophisticated rendering pipeline. Mastering this pipeline—specifically the concepts of reflow and repaint—is foundational for front-end performance optimization and essential for building buttery-smooth CSS animations.
A browser typically processes a webpage through five core stages:
- Parsing: Breaking down HTML and CSS into the DOM (Document Object Model) and CSSOM (CSS Object Model) trees respectively.
- Style Calculation: Merging the DOM and CSSOM to construct the render tree, identifying which nodes actually need to be displayed.
- Layout (Reflow): Calculating the exact coordinates, geometry, and sizes of every visible element within the viewport.
- Paint: Rasterizing the visual details—such as colors, borders, shadows, and text—onto pixel layers.
- Compositing: Merging multiple painted layers in the correct stacking order and outputting the final result to the screen.
While reflow corresponds directly to the layout phase and repaint to the paint phase, modern browsers also utilize a third, highly optimized path known as compositing, which bypasses the heavier steps altogether.
Reflow (sometimes referred to as layout) occurs when the geometric information of a render tree node changes—meaning its dimensions, position, or internal content require the browser to recalculate its layout.
Common triggers for reflow include:
- Initial page loading and rendering.
- Resizing the browser window.
- Adding, removing, or modifying visible DOM nodes.
- Changing geometry-related CSS properties such as
width,height,margin,padding,display, orposition. - Querying layout-sensitive properties like
offsetWidth,scrollTop, or invokinggetComputedStyle().
Because reflow recalculates coordinates for affected elements and their descendants, it is computationally expensive and can severely degrade frame rates if triggered too frequently.
What is Repaint?
Repaint happens when an element's visual appearance changes without altering its underlying geometric layout.
Common triggers for repaint include:
- Modifying pure visual properties like
color,background-color,visibility,box-shadow, orborder-radius. - Triggering hover states, focus changes, or visual highlights that leave element dimensions completely untouched.
Since the browser doesn't need to recalculate spatial coordinates, repaint is generally faster than reflow, but frequent paint cycles can still introduce noticeable stutter.
Relationship and Performance Cost
| Comparison Dimension | Reflow | Repaint |
|---|---|---|
| Pipeline Stage | Layout | Paint |
| Trigger Cause | Changes in geometry/position | Changes in visual appearance |
| Performance Cost | High | Moderate to Low |
| Dependencies | Always triggers a repaint | Does not necessarily trigger a reflow |
The golden rule is straightforward: A reflow will always trigger a subsequent repaint, but a repaint does not necessarily cause a reflow.
Furthermore, there is a third, highly efficient mechanism: Compositing. If you animate properties that can be handled entirely by the compositor thread—such as transform and opacity—the browser completely bypasses both layout and paint stages, resulting in optimal rendering performance.
The Pitfall of Forced Synchronous Layout
Interleaving read and write operations inside JavaScript loops is a classic performance trap. To return accurate layout metrics, browsers are forced to execute synchronous reflows on the spot:
// Anti-pattern: Interleaved reading and writing triggers multiple reflows
const box = document.getElementById('box');
for (let i = 0; i < 10; i++) {
box.style.width = box.offsetWidth + 10 + 'px';
}
The optimized approach is to batch your reads and writes separately—reading all necessary geometric properties first, then applying your updates:
const box = document.getElementById('box');
const currentWidth = box.offsetWidth; // Read once
box.style.width = currentWidth + 100 + 'px'; // Write once
Even better, batch multiple style changes into a single class modification to let the browser process everything in one controlled reflow.
Core Optimization Strategies
To minimize performance bottlenecks caused by reflow and repaint, incorporate these practices into your daily development workflow:
- Batch Style Modifications: Apply multiple changes at once using a CSS
classtoggle orcssTextrather than modifying individual properties sequentially. - Separate Reads and Writes: Avoid layout thrashing by gathering all DOM measurements before executing DOM mutations.
- Batch DOM Operations: Use a
DocumentFragment, or temporarily hide an element (display: none), perform bulk updates, and bring it back into the DOM tree. - Leverage the Compositor: For animations, rely heavily on
transformandopacityto keep work off the main thread. - Isolate Layout Changes: Apply
position: fixedorabsoluteto animated or frequently changing elements to contain the scope of any potential reflow. - Hint the Browser: Use
will-changeon complex elements to let the browser preemptively set up hardware acceleration layers.
Conclusion
Reflow and repaint represent two distinct stages in the browser's rendering pipeline with vastly different performance profiles. Reflow recalculates geometric layouts, while repaint only updates pixel appearances—with reflow invariably cascading into a repaint, and compositing offering the lightest-weight alternative. By mastering the core principles of batching modifications, separating reads from writes, and prioritizing compositor-friendly properties, you can eliminate performance bottlenecks and ensure smooth, responsive user experiences across all devices.