Rendering, Repaint & Reflow
Rendering, Repaint & Reflow
Section titled “Rendering, Repaint & Reflow”Introduction
Section titled “Introduction”When you change the DOM or CSS, the browser recalculates styles, lays out elements, and paints pixels. Understanding this pipeline helps you write performant code.
Topics Covered
Section titled “Topics Covered”- The Rendering Pipeline — Style calculation, layout, paint, and compositing
- Reflow Triggers — What causes layout recalculations and how to avoid them
- Compositing & GPU — Using transform and opacity for GPU-accelerated animations
The Rendering Pipeline
Section titled “The Rendering Pipeline”flowchart LR A["JavaScript"] --> B["Style Calculation"] B --> C["Layout (Reflow)"] C --> D["Paint (Repaint)"] D --> E["Composition"]Reflow (Layout)
Section titled “Reflow (Layout)”Reflow recalculates the position and size of elements. It’s expensive because it affects the entire document tree.
// ❌ Triggers reflow (expensive)element.style.width = '100px';element.style.height = '200px';element.style.margin = '10px';
// ✅ Batch reads/writes to avoid forced reflow// Read first, then writeconst height = element.offsetHeight; // Readelement.style.height = height + 10 + 'px'; // WriteWhat Triggers Reflow
Section titled “What Triggers Reflow”- Adding/removing DOM elements
- Changing dimensions (width, height, margin, padding)
- Changing font, font-size
- Changing positioning (position, top, left)
offsetHeight,offsetWidth,getBoundingClientRect()(read)
Repaint (Paint)
Section titled “Repaint (Paint)”Repaint happens when visual changes don’t affect layout — like changing color, background-color, visibility, or outline.
// ✅ Only triggers repaint (cheaper)element.style.color = 'red';element.style.backgroundColor = '#f0f0f0';
// ❌ Triggers reflow (expensive)element.style.width = '50%';Compositing (GPU)
Section titled “Compositing (GPU)”The most performant changes only trigger compositing — they don’t affect layout or paint:
// ✅ Only triggers compositing (fastest!)element.style.transform = 'rotate(45deg)';element.style.opacity = '0.5';Best Practices
Section titled “Best Practices”// 1. Use CSS classes instead of inline styles (batch changes)element.classList.add('active');
// 2. Use transform/opacity for animations (GPU accelerated)element.style.transform = 'translateX(100px)';
// 3. Minimize layout thrashing — read, then writeconst width = element.offsetWidth; // Read onceelements.forEach(el => { el.style.width = (width / 2) + 'px'; // Write many times});
// 4. Use DocumentFragment for batch DOM insertionsconst fragment = document.createDocumentFragment();items.forEach(item => fragment.appendChild(createElement(item)));container.appendChild(fragment);
// 5. Use content-visibility for off-screen content// CSS: content-visibility: autoSummary
Section titled “Summary”| Change | Cost | Properties |
|---|---|---|
| Reflow | Expensive | width, height, margin, font |
| Repaint | Moderate | color, background, visibility |
| Compositing | Cheap 🚀 | transform, opacity |