All topics
Performanceintermediate

requestAnimationFrame and Smooth Animations

A browser API for scheduling visual updates in sync with the display's refresh cycle, producing smoother animations than setTimeout-based approaches.

requestAnimationFrame (rAF) is a browser API specifically designed for scheduling code that updates the screen's visuals, synchronized precisely with the browser's own natural rendering cycle — typically matching the display's refresh rate (commonly 60Hz, meaning roughly every 16.7ms) — which produces visibly smoother, more efficient animations than driving the same updates with setTimeout or setInterval, which have no inherent awareness of the browser's actual rendering schedule at all.

requestAnimationFrame is like a stagehand who only makes their next scenery change exactly when the curtain is about to rise for the next scene, perfectly timed to the actual show's pacing — versus a stagehand on a fixed independent stopwatch (setTimeout) who might make changes mid-scene, out of sync with what the audience is actually about to see, wasting effort or causing visible jank either way.

Key Concepts

1
Calling requestAnimationFrame(callback) schedules callback to run once, immediately before the browser's next repaint — not at some arbitrary fixed millisecond delay like setTimeout, but precisely timed to align with when the browser is actually about to redraw the screen anyway. For a continuous animation, the callback itself calls requestAnimationFrame again at its end, recursively scheduling the next frame, which naturally paces the animation to the display's actual refresh rate rather than an arbitrary, potentially mismatched timer interval that could cause visible stuttering (updating faster than the screen can display, wasting work) or choppiness (updating slower than the display refreshes, causing dropped frames).
requestAnimationFrame(callback)callbacksetTimeoutrequestAnimationFrame
2
A major practical advantage: the browser automatically pauses requestAnimationFrame callbacks entirely when a tab isn't visible (backgrounded or minimized), which both saves battery/CPU on inactive tabs and avoids a burst of accumulated, backlogged animation work suddenly executing all at once when the user switches back to the tab — setInterval-based animations don't get this automatic pause-and-resume behavior for free, and naively resuming a setInterval-driven animation after being backgrounded can cause a visible jump or a rapid catch-up burst.
requestAnimationFramesetInterval
3
Because requestAnimationFrame's callback receives a high-resolution timestamp argument representing the current frame's time, smooth, frame-rate-independent animations are built by calculating elapsed time between frames (rather than assuming a fixed, uniform time delta per callback) and scaling the animation's progress by that actual elapsed time — this ensures the animation completes in the same real-world duration regardless of whether the display happens to be running at 60Hz, 120Hz, or has briefly dropped frames due to other load on the system.
requestAnimationFrame