Window: requestAnimationFrame() method - Web APIs | MDN
Skip to search
Window: requestAnimationFrame() method
Baseline
Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015.
See full compatibility
Report feedback
The
window.requestAnimationFrame()
method tells the
browser you wish to perform an animation. It requests the browser to call a
user-supplied callback function before the next repaint.
The frequency of calls to the callback function will generally match the display
refresh rate. The most common refresh rate is 60hz,
(60 cycles/frames per second), though 75hz, 120hz, and 144hz are also widely used.
requestAnimationFrame()
calls are paused in most browsers when running in
background tabs or hidden
function step(timestamp) {
if (start === undefined) {
start = timestamp;
const elapsed = timestamp - start;
// Math.min() is used here to make sure the element stops at exactly 200px
const shift = Math.min(0.1 * elapsed, 200);
element.style.transform = `translateX(${shift}px)`;
if (shift < 200) {
requestAnimationFrame(step);
requestAnimationFrame(step);
The following three examples illustrate different approaches to setting the zero point in time,
the baseline for calculating the progress of your animation in each frame. If you
want to synchronize to an external clock, such as
BaseAudioContext.currentTime
the highest precision available is the duration of a single frame, 16.67ms @60Hz. The
callback's timestamp argument represents the end of the previous frame, so the soonest
your newly calculated value(s) will be rendered is in the next frame.
This example waits until the first callback executes to set
zero
. If your animation
jumps to a new value when it starts, you must structure it this way. If you do not need to
synchronize to anything external, such as audio, then this approach is recommended because
some browsers have a multi-frame delay between the initial call to
requestAnimationFrame()
and the first call to the callback function.
js
let zero;
requestAnimationFrame(firstFrame);
function firstFrame(timestamp) {
zero = timestamp;
animate(timestamp);
function animate(timestamp) {
const value = (timestamp - zero) / duration;
if (value < 1) {
element.style.opacity = value;
requestAnimationFrame((t) => animate(t));
} else element.style.opacity = 1;
This example uses
document.timeline.currentTime
to set a zero value
before the first call to
requestAnimationFrame
document.timeline.currentTime
aligns with the
timestamp
argument, so the zero value is equivalent to the
0th frame's timestamp.
js
const zero = document.timeline.currentTime;
requestAnimationFrame(animate);
function animate(timestamp) {
const value = (timestamp - zero) / duration; // animation-timing-function: linear
if (value < 1) {
element.style.opacity = value;
requestAnimationFrame((t) => animate(t));
} else element.style.opacity = 1;
This example animates using
performance.now()
instead of the callback's
timestamp value. You might use this to achieve slightly higher synchronization
precision, though the extra degree of precision is variable and not much of an increase.
Note:
This example does not allow you to synchronize animation callbacks reliably.
js
const zero = performance.now();
requestAnimationFrame(animate);
function animate() {
const value = (performance.now() - zero) / duration;
if (value < 1) {
element.style.opacity = value;
requestAnimationFrame(animate);
} else element.style.opacity = 1;
Specifications
Specification
HTML
# dom-animationframeprovider-requestanimationframe
Browser compatibility
See also
Window.cancelAnimationFrame()
DedicatedWorkerGlobalScope.requestAnimationFrame()
Animating with JavaScript: from setInterval to requestAnimationFrame
- Blog post
TestUFO: Test your web browser for requestAnimationFrame() Timing Deviations
Firefox switching to uint32_t for the requestAnimationFrame request ID
Help improve MDN
Learn how to contribute
This page was last modified on
Dec 26, 2025
by
MDN contributors
View this page on GitHub
Report a problem with this content