Skip to main content Accessibility Feedback

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.

Here’s a demo.

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.