DOM Manipulation and Browser APIsLesson 5.5
Timers, requestAnimationFrame, and browser rendering performance
setTimeout, setInterval, clearTimeout clearInterval, requestAnimationFrame, requestIdleCallback, animation loop pattern, layout thrashing, will-change, performance.now
Scheduling Work at the Right Time
JavaScript provides several scheduling APIs. Choosing the right one for animations, timers, and deferred work prevents janky interfaces and wasted CPU cycles. The browser renders at roughly 60 frames per second — every 16ms. Your code must work within that budget.
setTimeout and setInterval
const id = setTimeout(() => console.log("After 1s"), 1000);
clearTimeout(id); // cancel before it fires
const tick = setInterval(() => updateClock(), 1000);
clearInterval(tick); // always clean up when done
requestAnimationFrame — Smooth Animations
Runs your callback just before the browser paints the next frame. Automatically syncs to the display refresh rate and pauses when the tab is hidden — saving battery and CPU.
function animate(timestamp) {
const elapsed = timestamp - startTime;
element.style.transform = `translateX(${elapsed * 0.1}px)`;
if (elapsed < 1000) {
requestAnimationFrame(animate); // schedule next frame
}
}
const startTime = performance.now();
requestAnimationFrame(animate);
Avoiding Layout Thrashing
// BAD — interleaved reads/writes force reflow each iteration
boxes.forEach(box => {
const h = box.offsetHeight; // read — triggers layout
box.style.height = h * 2 + "px"; // write
});
// GOOD — batch all reads, then all writes
const heights = boxes.map(b => b.offsetHeight);
boxes.forEach((box, i) => box.style.height = heights[i] * 2 + "px");
