Browser Rendering Principles: Understanding Reflow and Repaint is Key to Optimization

Chris's ambitious animated menu feels sluggish for some reason.
"It's a brand new MacBook, so why is it stuttering like this?"
Opening the code, he found that he was increasing the width value by 1px repeatedly using JavaScript to open the menu. Chris had effectively just forced the browser into extreme overwork.
No matter how efficient React's Virtual DOM is, if you don't understand the principle of how the browser actually draws the screen, your performance optimization will only be half-complete. Today, we dig into the process of the browser stamping pixels onto the screen: the Critical Rendering Path.
The Browser's Factory Line: The Rendering Pipeline
From receiving an HTML file to displaying it on the screen, the browser goes through a specific assembly line.
The core of performance optimization depends on how much you can reduce steps 4 (Layout) and 5 (Paint).
Reflow and Repaint: The Main Culprits of Performance Costs
1. Reflow (Layout): "Calculate it again!"
This is the most expensive operation. If an element's geometric information (width, height, position) changes, the browser must recalculate the layout not just for that element, but also for its affected children, parents, and potentially the entire document.
It's like moving a sofa in the living room by 1cm, and then having to measure the position of every other piece of furniture in the house all over again with a ruler.
Properties that trigger Reflow:
2. Repaint (Paint): "Just recolor it!"
This is cheaper than Reflow but still incurs a cost. It occurs when the layout (position, size) doesn't change, but the visible style does.
Properties that trigger Repaint:
Important: If a Reflow occurs, a Repaint always occurs subsequently. If the position changes, the browser obviously has to draw it again.
Optimization Strategy: Leverage the GPU (Composite)
So, how do we make animations smooth (60fps)?
The answer is to skip the Layout and Paint stages entirely.
Browsers have properties that only go through the Composite stage. These are processed by the GPU, not the CPU, making them extremely fast.
❌ Bad Example: Torturing the CPU
This is the code Chris wrote. Changing the left property causes a Reflow every single frame.
/* style.css */
.box {
position: absolute;
left: 10px;
transition: left 0.5s;
}
.box.move {
/* Layout(Reflow) Triggered! -> Paint Triggered! -> Slow */
left: 100px;
}✅ Good Example: Offloading to the GPU
transform and opacity skip the layout and paint stages and jump straight to the Composite stage.
/* style.css */
.box {
/* Separated into its own layer for GPU acceleration */
transform: translateX(10px);
transition: transform 0.5s;
}
.box.move {
/* Only Composite Triggered! -> Fast */
transform: translateX(100px);
}Forced Synchronous Layout (Layout Thrashing)
A single line of JavaScript can ruin performance. Browsers normally optimize rendering by batching changes and processing them at once. However, if we try to read a specific layout value, the browser is forced to clear the queue and calculate the layout immediately to give you the accurate value.
// layout-thrashing.js
const box = document.getElementById('box');
// 1. Write Style
box.style.width = '100px';
// 2. Read Style -> 💥 Forced Layout!
// Browser: "Wait, you changed the width, so to give you the accurate clientWidth, I have to calculate (Reflow) right now."
console.log(box.clientWidth);
// 3. Write Again
box.style.height = '100px';To prevent this, avoid mixing Reads and Writes. Perform all reads first, then writes, or utilize requestAnimationFrame.
Key Takeaways
Optimization Tip: When creating animations, turn on Paint Flashing in the 'Rendering' tab of Chrome DevTools and visually check how much of the green area is being redrawn.
Now that we understand how the browser draws pictures, it's time to learn how to reduce network costs. How can we ensure users don't have to download an image again after they've received it once?
Continuing in: "The Complete Guide to HTTP Caching: Cutting Network Costs with Cache-Control and ETag"