Performance and DevTools
Use requestAnimationFrame for visual updates
Schedule work that changes the current frame near the browser’s next rendering opportunity.
8 minute lesson
requestAnimationFrame() asks the browser to run a callback before a future paint. It is a good place to apply a visual state that should be synchronized with rendering.
let start
function move(timestamp) {
start ??= timestamp
const elapsed = timestamp - start
const x = Math.min(elapsed / 4, 300)
box.style.transform = `translateX(${x}px)`
if (x < 300) requestAnimationFrame(move)
}
requestAnimationFrame(move)
Use the callback timestamp rather than assuming a fixed number of frames per second. Displays have different refresh rates, frames can be delayed, and browsers usually reduce or pause callbacks in background tabs.
requestAnimationFrame does not make expensive work fast. A callback that runs too long still delays the frame. Keep it focused on the state needed for that paint, and move unrelated work elsewhere.
For repeated events such as scroll, store the latest input and schedule at most one pending frame:
let scheduled = false
window.addEventListener('scroll', () => {
if (scheduled) return
scheduled = true
requestAnimationFrame(() => {
updateHeader(window.scrollY)
scheduled = false
})
})
Record the animation with the Performance panel. Check frame timing and the duration of each callback. If frames remain late, investigate the callback and the rendering it triggers instead of adding another scheduling layer.
Lesson completed