Smoother JS Animations with requestAnimationFrame

Within Javascript, if you ever worked on creating animations you’ve probably been dependent on the setTimeout() or setInterval() functions to do much of the work for you – incrementing a value at each execution and moving or changing an element. The situation in the code snippet below might look familiar, a function which contains a setTimeout() which changes a value, either continueously by calling itself or until a point by checking a condition with an if statement.

(function animate() {
    setTimeout(function() {
        if (m < limit) { animate(); }
        m += 20;
        e.style.top = m + 'px';
    }, speed);
})();

This code works. And animations have worked like this for sometime, the only downside is that the browser will treat it like any other JS executing – on an individual basis. As a result browsers have begun implementing a new API called requestAnimationFrame() which allows browsers to know the sort of JS being executed (often visually heavy) allowing them to act accordingly.

The advantages of using the requestAnimationFrame API are that:

  • Browsers can bundle any animations happening at the same time into a single paint redraw (thus happening faster/with less CPU cycles).
  • If the JS execution is occuring in a tab which is not visible it doesn’t have to be drawn.
  • By calling browser implementations of this, the execution can happen in the most efficient manner for the operation.

To rewrite the code snippet above using the requestAnimationFrame API (and a helpful polyfil by Erik Möller to make it browser compatible):

(function animate() {
    if (m < limit) { window.requestAnimationFrame(animate); }
    m += 20;
    e.style.top = m + 'px';
})();

View Demo / Comparison

Two articles in particular were insightful about this, the first being a post from 2011 by Paul Irish ‘requestAnimationFrame for Smart Animating’ and the second being an article comparing CSS animation performace to JS animations on David Walsh’s blog.

Using requestAnimationFrame? Notice any difference? Tell us in the comments.