How requestAnimationFrame Synchronizes JS Animations
The window.requestAnimationFrame() API is a native
browser method designed to execute smooth, performant JavaScript
animations. This article explores how requestAnimationFrame
works, why it replaced legacy timer-based methods like
setInterval and setTimeout, and how it
synchronizes animation updates directly with the user’s display refresh
rate to eliminate visual stutter and conserve system resources.
What is requestAnimationFrame?
The requestAnimationFrame (rAF) method tells the browser
that a script wishes to perform an animation and requests that the
browser call a specified callback function before the next repaint.
Instead of forcing the browser to render changes at arbitrary
intervals, requestAnimationFrame yields rendering control
to the browser. The browser then executes the callback right before the
screen updates, typically matching the display’s native refresh rate
(such as 60Hz, 120Hz, or 144Hz).
The Limitations of Legacy Animation Methods
Before requestAnimationFrame, developers relied on
setTimeout() and setInterval() to create
animations by incrementally updating element styles over fixed
millisecond intervals. This approach has critical drawbacks:
- Frame Rate Mismatches: Displays typically refresh
every 16.67 milliseconds (at 60 frames per second).
setIntervalruns independently of the display hardware clock. If a timer fires in the middle of a refresh cycle, the browser cannot draw the frame immediately, leading to dropped frames and visual stutter (jank). - Display Tearing and Redundant Execution: Timers may execute multiple times within a single screen refresh, causing unnecessary DOM calculations and screen tearing without improving visual quality.
- Resource Inefficiency: Timers continue running at full speed even if the user minimizes the window or switches to another tab, wasting CPU/GPU resources and battery power.
How requestAnimationFrame Synchronizes Animations
The requestAnimationFrame API resolves these issues by
coordinating JavaScript execution directly with the browser’s internal
rendering pipeline through several mechanisms:
1. Vertical Synchronization (VSync) Alignment
Displays rely on vertical synchronization (VSync) signals to draw new
frames cleanly from top to bottom. requestAnimationFrame
queues JavaScript callbacks to run in sync with the hardware VSync tick.
By aligning execution to this cycle, the browser ensures that state
changes are computed and painted precisely when the screen is ready to
display them.
2. High-Resolution Timestamps
When the browser executes the callback registered with
requestAnimationFrame, it automatically passes a
high-resolution timestamp (DOMHighResTimeStamp)
representing the exact time the frame started rendering. Developers use
this timestamp to calculate time-based deltas rather than frame-based
deltas:
let start;
function animate(timestamp) {
if (!start) start = timestamp;
const elapsed = timestamp - start;
// Move an element based on elapsed time (e.g., 0.1px per millisecond)
element.style.transform = `translateX(${Math.min(0.1 * elapsed, 200)}px)`;
if (elapsed < 2000) {
// Request the next frame
window.requestAnimationFrame(animate);
}
}
// Start the animation
window.requestAnimationFrame(animate);Using time deltas guarantees that animations progress at a consistent real-world speed regardless of whether the device runs at 60Hz, 120Hz, or experiences a temporary frame drop.
3. Rendering Pipeline Optimization
When using requestAnimationFrame, the browser batches
multiple style recalculations, layout steps, and paints into a single
reflow cycle. This prevents layout thrashing and reduces the overall
computational load on the main thread.
4. Automatic Power and Tab Throttling
If a user navigates to a different tab or minimizes the browser
window, the browser automatically pauses or severely throttles
requestAnimationFrame loops. Execution resumes seamlessly
when the tab returns to the foreground, eliminating background CPU and
battery drain.
Summary
requestAnimationFrame synchronizes JavaScript animations
by integrating script execution directly into the browser’s
hardware-aligned rendering loop. By replacing fixed-interval timers with
VSync-aligned frame requests, it delivers stutter-free rendering,
optimized computational overhead, and improved energy efficiency.