
Reduce Reflows and Repaints
Reduce Reflows and Repaints 관련
Browser Rendering Process
- Parse HTML to generate DOM tree.
- Parse CSS to generate CSSOM rules tree.
- Combine DOM tree and CSSOM rules tree to generate rendering tree.
- Traverse the rendering tree to begin layout, calculating the position and size information of each node.
- Paint each node of the rendering tree to the screen.
Reflow
When the position or size of DOM elements is changed, the browser needs to regenerate the rendering tree, a process called reflow.
Repaint
After regenerating the rendering tree, each node of the rendering tree needs to be painted to the screen, a process called repaint. Not all actions will cause reflow – for example, changing font color will only cause repaint. Remember, reflow will cause repaint, but repaint will not cause reflow.
Both reflow and repaint operations are very expensive because the JavaScript engine thread and the GUI rendering thread are mutually exclusive, and only one can work at a time.
What operations will cause reflow?
- Adding or removing visible DOM elements
- Element position changes
- Element size changes
- Content changes
- Browser window size changes
How to reduce reflows and repaints?
- When modifying styles with JavaScript, it's best not to write styles directly, but to replace classes to change styles.
- If you need to perform a series of operations on a DOM element, you can take the DOM element out of the document flow, make modifications, and then bring it back to the document. It's recommended to use hidden elements (display:none) or document fragments (DocumentFragement), both of which can implement this approach well.
Example of causing unnecessary reflows (inefficient):
// This causes multiple reflows as each style change triggers a reflow
const element = document.getElementById('myElement');
element.style.width = '100px';
element.style.height = '200px';
element.style.margin = '10px';
element.style.padding = '20px';
element.style.borderRadius = '5px';
Optimized version 1 – using CSS classes:
.my-modified-element {
width: 100px;
height: 200px;
margin: 10px;
padding: 20px;
border-radius: 5px;
}
// Only one reflow happens when the class is added
document.getElementById('myElement').classList.add('my-modified-element');
Optimized version 2 – batching style changes:
// Batching style changes using cssText
const element = document.getElementById('myElement');
element.style.cssText = 'width: 100px; height: 200px; margin: 10px; padding: 20px; border-radius: 5px;';
Optimized version 3 – using document fragments (for multiple elements):
// Instead of adding elements one by one
const list = document.getElementById('myList');
const fragment = document.createDocumentFragment();
for (let i = 0; i < 100; i++) {
const item = document.createElement('li');
item.textContent = `Item ${i}`;
fragment.appendChild(item);
}
// Only one reflow happens when the fragment is appended
list.appendChild(fragment);
Optimized version 4 – take element out of flow, modify, then reinsert:
// Remove from DOM, make changes, then reinsert
const element = document.getElementById('myElement');
const parent = element.parentNode;
const nextSibling = element.nextSibling;
// Remove (causes one reflow)
parent.removeChild(element);
// Make multiple changes (no reflows while detached)
element.style.width = '100px';
element.style.height = '200px';
element.style.margin = '10px';
element.style.padding = '20px';
element.style.borderRadius = '5px';
// Reinsert (causes one more reflow)
if (nextSibling) {
parent.insertBefore(element, nextSibling);
} else {
parent.appendChild(element);
}
Optimized version 5 – using display:none temporarily:
const element = document.getElementById('myElement');
// Hide element (one reflow)
element.style.display = 'none';
// Make multiple changes (no reflows while hidden)
element.style.width = '100px';
element.style.height = '200px';
element.style.margin = '10px';
element.style.padding = '20px';
element.style.borderRadius = '5px';
// Show element again (one more reflow)
element.style.display = 'block';
By using these optimization techniques, you can significantly reduce the number of reflows and repaints, leading to smoother performance, especially for animations and dynamic content updates.