Reducing Reflow and Repaint
In this page:
What are Reflow and Repaint?
A reflow is the browser recalculating the position and size of elements on the page, which is comparatively expensive if it gets triggered repeatedly in a short span of time. Reading certain layout properties right after changing styles is one of the most common ways to accidentally force extra reflows.
Example: What are Reflow and Repaint?
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body>
<div id="box">Box</div>
<script>
$("#box").css("width", "200px");
console.log($("#box")[0].offsetHeight);
</script>
</body>
</html>
Batch DOM Updates
Making many separate DOM changes in a row — appending elements one at a time in a loop, for instance — can each individually trigger extra layout work. Building the full set of changes first (in memory, or in a detached fragment) and inserting them into the page in one operation avoids that repeated cost.
Example: Batch DOM Updates
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body>
<ul id="list"></ul>
<script>
let html = "";
for (let i = 0; i < 5; i++) {
html += "<li>Item " + i + "</li>";
}
$("#list").html(html);
</script>
</body>
</html>
Use Classes Instead of Many Styles
Changing one CSS class can update several style properties at once, since the class itself can bundle color, size, spacing, and more into a single rule. This keeps the JavaScript simpler than setting several individual style properties directly, and it also tends to reduce how many separate style changes the browser has to process.
Example: Use Classes Instead of Many Styles
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<style>
.highlighted { background: yellow; border: 1px solid orange; padding: 4px; }
</style>
</head>
<body>
<div id="box">Box</div>
<script>
$("#box").addClass("highlighted");
</script>
</body>
</html>
Avoid Unnecessary Layout Reads
Reading layout values — like an element's offsetHeight or getBoundingClientRect() — right after changing its styles can force the browser to recalculate layout immediately instead of waiting, since it needs an up-to-date answer. Grouping all your reads together before making any writes avoids triggering that recalculation repeatedly.
Example: Avoid Unnecessary Layout Reads
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body>
<div id="box">Box</div>
<script>
$("#box").css("width", "300px");
setTimeout(function() {
console.log($("#box")[0].offsetHeight);
}, 0);
</script>
</body>
</html>
Small Performance Project
Good DOM performance practice combines a few habits: batching DOM updates together, caching selectors instead of re-querying, and preferring CSS class changes over many individual style changes — all of which reduce how much layout and paint work the browser has to redo.
Example: Small Performance Project
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body>
<ul id="list"></ul>
<script>
const $list = $("#list");
let html = "";
for (let i = 0; i < 3; i++) {
html += "<li>Row " + i + "</li>";
}
$list.html(html);
</script>
</body>
</html>
Chapter Quiz — Complete all 5 topics to unlock
0/5 topics done
Complete these topics first: