What does requestAnimationFrame() do?
Definition
requestAnimationFrame(callback) is a built-in browser API
that schedules the callback function to run before the next repaint (before the "screen redraw").
What this means in practice
When the browser is about to repaint the screen (typically ~60 times per second, i.e. every 16.6 ms),
it calls your callback from requestAnimationFrame at the optimal moment,
so the animation looks as smooth as possible without jank.
Example
function animate(time) {
console.log('Frame at', time, 'ms');
requestAnimationFrame(animate); // request the next frame
}
requestAnimationFrame(animate);What happens here:
animateis called before every repaint;timeis a timestamp (in milliseconds) showing when the frame's repaint actually started (perperformance.now()).
How this works under the hood
- You call
requestAnimationFrame(fn); - The function
fnis stored by the browser; - When the browser is ready to draw a new frame (usually after 16 ms), it calls all such functions right before repainting;
- After the callback runs, the browser repaints the screen.
If you call requestAnimationFrame() again inside the callback,
the animation runs in a loop, frame after frame.
Example: smooth element movement
const box = document.querySelector('.box');
let start = null;
function move(timestamp) {
if (!start) start = timestamp;
const progress = timestamp - start;
box.style.transform = `translateX(${progress / 5}px)`;
if (progress < 2000) { // 2 seconds
requestAnimationFrame(move);
}
}
requestAnimationFrame(move);Here the element moves smoothly over 2 seconds.
And the browser optimizes calls itself: if the tab isn't visible,
requestAnimationFrame pauses so it doesn't waste resources.
Difference from setTimeout / setInterval
| Criterion | setTimeout / setInterval | requestAnimationFrame |
|---|---|---|
| Frequency | Fixed (for example, every 16 ms) | Synchronized with the screen refresh rate |
| Power usage | Not paused in background tabs | Automatically stops when the tab is hidden |
| Smoothness | Can "stutter" under load | Maximally smooth repainting |
| Usage | Timers, background tasks | Animations, smooth UI updates |
| Passes a timestamp | No | Yes (performance.now() frame time) |
Comparison example
function moveWithTimeout() {
box.style.left = `${parseInt(box.style.left || 0) + 1}px`;
setTimeout(moveWithTimeout, 16);
}
function moveWithRaf() {
box.style.left = `${parseInt(box.style.left || 0) + 1}px`;
requestAnimationFrame(moveWithRaf);
}setTimeout doesn't account for browser load and can "skip" frames.
requestAnimationFrame adapts to the display's refresh rate and is always as smooth as possible.
Canceling a call
If you need to cancel a scheduled frame:
const id = requestAnimationFrame(step);
cancelAnimationFrame(id);SUMMARY
| Property | Description |
|---|---|
| What it does | Runs a callback before the next repaint |
| When it's called | When the browser is ready to draw a new frame (~60 FPS) |
| Function argument | timestamp - the frame's start time |
| Returns | A frame ID (for cancelAnimationFrame) |
| Stops automatically | Yes, when the tab is inactive |
| Task type | A separate queue for visual updates (before rendering) |
| Ideal for | Animations, smooth transforms, progress bars |
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.