requestAnimationFrame (rAF)
`requestAnimationFrame` schedules a callback for a future browser animation frame, typically just before the browser paints the next frame. It is commonly used to coordinate JavaScript-driven visual updates with rendering.
Calling `requestAnimationFrame(callback)` asks the browser to invoke `callback` before a subsequent repaint. The callback receives a timestamp representing the frame's timing, which can be used to calculate time-based animation progress.
A common pattern is to update visual state, schedule the next frame, and let the browser handle when the frame should be rendered. This is generally preferable to using a fixed `setInterval` loop for animations because the callback is coordinated with the browser's rendering cycle.
The callback is not guaranteed to run at a particular frequency, and it can be delayed when the page is busy or the document is not actively visible. Therefore, animation code should use the supplied timestamp or elapsed time rather than assuming a fixed interval between frames.
`requestAnimationFrame` returns an identifier that can be passed to `cancelAnimationFrame` to cancel a pending callback. If an animation needs to continue, the callback normally schedules another frame explicitly.
Key points
- Schedules a callback for a future rendering frame.
- Designed for JavaScript-driven visual updates and animations.
- Use the callback timestamp or elapsed time instead of assuming 60 FPS.
- Call `cancelAnimationFrame` with the returned ID to cancel a pending callback.
- A recurring animation normally schedules the next frame from within the current callback.
Interview questions
Why can an rAF-based animation still drop frames?
rAF aligns animation work with rendering, but it does not make the work itself inexpensive. If the callback or other main-thread work takes too long, the browser may miss a rendering opportunity. Long JavaScript tasks, layout work, style recalculation, or excessive DOM updates can therefore reduce smoothness. rAF should be paired with efficient rendering work rather than treated as a guarantee of smooth animation.
What happens to rAF when a page is backgrounded or otherwise not actively visible?
Browsers can throttle or pause animation callbacks for documents that are not actively visible. This is an important reason not to use rAF as a general-purpose timer. Animation logic should tolerate irregular callback timing and derive progress from timestamps when appropriate. If an application needs guaranteed scheduling semantics independent of rendering visibility, another mechanism may be more appropriate.
What problem does `requestAnimationFrame` solve?
It provides a browser-aware way to schedule JavaScript work for visual updates. The callback is intended to run before a repaint, so animation logic can be synchronized with rendering. This avoids treating animation as an ordinary timer loop. It is especially useful when JavaScript needs to calculate changing visual state.
Why should an animation use the rAF timestamp instead of assuming one frame equals a fixed amount of movement?
The interval between animation frames is not guaranteed to be constant. Displays can have different refresh rates, and callbacks can be delayed by browser or application work. Using the supplied timestamp lets the animation calculate progress from elapsed time. This keeps time-based motion much more consistent across varying frame rates.
How would you implement a continuous rAF animation and stop it safely?
Start the animation with `requestAnimationFrame` and store the returned identifier. Inside the callback, update the visual state and request the next frame if the animation should continue. When stopping, cancel the pending identifier with `cancelAnimationFrame`. In component-based applications, cleanup should cancel the outstanding frame when the component is removed.