How to use requestAnimationFrame() with vanilla JS
The requestAnimationFrame()
method tells the browser to run a callback function right before the next repaint happens.
It’s particularly useful when using JavaScript for animations and repeating UI updates. Because it ties into the browser’s repaint timing, it produces a smoother effect than using something like setInterval()
.
Let’s look at how it works.
Creating a callback function
The requestAnimationFrame()
method accepts one argument: a callback function to run.
window.requestAnimationFrame(function () {
console.log('it ran!');
});
The callback function runs just before the next time the browser runs a repaint. On modern devices, that typically happens 60 times per second.
Looping animations
The requestAnimationFrame()
method only runs once. You can make it loop over-and-over again using a technique called recursion.
Let’s say you wanted to count from 0 up to 500, and update the UI each time.
First, we’ll use document.querySelector()
to get the element in the UI, and define a starting number
of 0
.
var counter = document.querySelector('#counter');
var number = 0;
With this technique, instead of using an anonymous function with requestAnimationFrame()
, you create a named one.
For our example, we’ll create a countUp()
function that increases number
by 1
, then sets it as the textContent
for the counter
element.
var counter = document.querySelector('#counter');
var number = 0;
var countUp = function () {
// Increase number by 1
number++;
// Update the UI
counter.textContent = number;
};
Now, here’s where the recursion comes in.
Inside the countUp()
function, we’ll call window.requestAnimationFrame()
, and pass the countUp()
function itself in as the callback function. This will cause it to run again just before the next repaint.
var counter = document.querySelector('#counter');
var number = 0;
var countUp = function () {
// Increase number by 1
number++;
// Update the UI
counter.textContent = number;
// if the number is less than or equal to 100,000, run it again
if (number <= 100000) {
window.requestAnimationFrame(countUp);
}
};
Finally, we’ll use window.requestAnimationFrame()
to start the animation.
var counter = document.querySelector('#counter');
var number = 0;
var countUp = function () {
// Increase number by 1
number++;
// Update the UI
counter.textContent = number;
// if the number is less than 500, run it again
if (number < 500) {
window.requestAnimationFrame(countUp);
}
};
// Start the animation
window.requestAnimationFrame(countUp);
Here’s a working demo you can play with.
Canceling requestAnimationFrame()
If you assign your requestAnimationFrame()
method to a variable, you can use the cancelAnimationFrame()
method to cancel it before it runs.
// Setup the animation
var animation = window.requestAnimationFrame(function () {
console.log('ran!');
});
// Cancel it
window.cancelAnimationFrame(animation);
In this demo, the callback function never runs.
Browser Compatibility
The requestAnimationFrame()
method works in all moderns browsers, and back to IE 10. You can push support back to IE6 with a polyfill.