Understanding requestAnimationFrame in JavaScript

The window.requestAnimationFrame() method is a dedicated browser API designed to synchronize JavaScript visual updates and animations directly with the display’s refresh rate. By scheduling execution immediately before the browser performs its next repaint, it eliminates animation stutter, prevents screen tearing, and reduces unnecessary resource consumption compared to legacy timer-based approaches like setTimeout and setInterval.

Synchronizing with Display Refresh Rates

Modern computer displays typically refresh at a rate of 60Hz (60 frames per second), 120Hz, or higher. When creating animations with legacy timers such as setInterval, callbacks execute at arbitrary intervals that do not align with the hardware’s refresh cycle. This mismatch often triggers frame rendering halfway through a screen refresh cycle, causing visible glitches known as jank or screen tearing.

requestAnimationFrame solves this by allowing the browser to dictate the timing. The browser calls the supplied callback function right before updating the screen, ensuring that each calculated frame corresponds directly to a single hardware display refresh.

Preventing Redundant Calculations

When using standard timers with intervals set too low (for example, attempting 100 updates per second on a 60Hz screen), the browser calculates visual states that are never actually rendered. requestAnimationFrame automatically matches the execution frequency to the user’s specific monitor capabilities, guaranteeing that no processing power is wasted calculating invisible intermediate frames.

Optimizing Battery and Resource Usage

A major advantage of requestAnimationFrame is its integration with browser tab visibility:

Alignment with the Browser Rendering Pipeline

During every frame lifecycle, the browser runs through a specific pipeline: executing JavaScript, calculating styles, computing layout (reflow), painting pixels, and compositing layers. requestAnimationFrame callbacks execute at the very start of this rendering pipeline. This ensures that any DOM modifications or style calculations made in JavaScript are processed and rendered in a single, unified pass, preventing layout thrashing and unnecessary repaints.

Basic Usage Pattern

Implementing a render loop with requestAnimationFrame involves recursively passing an update function to the API:

function animate(timestamp) {
  // Update visual state (e.g., element position, canvas drawing)
  element.style.transform = `translateX(${position}px)`;

  // Request the next frame
  requestAnimationFrame(animate);
}

// Start the animation loop
requestAnimationFrame(animate);

The callback function receives a high-precision DOMHighResTimeStamp indicating the exact time the frame was scheduled, allowing developers to calculate delta time and build frame-rate independent animations.