Grow your CSS skills. Land your dream job.

Using requestAnimationFrame

Published by Chris Coyier

There used to be just one way to do a timed loop in JavaScript: setInterval(). If you needed to repeat something pretty fast (but not as-fast-as-absolutely-possible like a for loop), you'd use that. For the purposes of animation, the goal is sixty "frames" per second to appear smooth, so you'd run a loop like this:

setInterval(function() {
  // animiate something
}, 1000/60);

There is a better alternative to this now. Paul Irish introduced requestAnimationFrame over two years ago. I don't have a whole lot to add to it, I just had never actually used it before and now I have so I thought I'd help spread the word and write about its basic usage.

Why better?

As Paul explained:

  • The browser can optimize it, so animations will be smoother
  • Animations in inactive tabs will stop, allowing the CPU to chill
  • More battery-friendly

The Simplest Possible Example

function repeatOften() {
  // Do whatever
  requestAnimationFrame(repeatOften);
}
requestAnimationFrame(repeatOften);

Call it once to kick it off, and your function recursively calls itself.

Start and Stop

requestAnimationFrame returns an ID you can use to cancel it, just like setTimeout or setInterval does. jQuery used here only to demonstrate a simple animation and bind events.

var globalID;

function repeatOften() {
  $("<div />").appendTo("body");
  globalID = requestAnimationFrame(repeatOften);
}

$("#start").on("click", function() {
  globalID = requestAnimationFrame(repeatOften);
});

$("#stop").on("click", function() {
  cancelAnimationFrame(globalID);
});

Example of this:

Check out this Pen!

Browser Support

See the Can I Use... tables.

The only notable problems are IE 9-, iOS 5-, and Android. But not actually a problem, because:

Polyfill

Like many fancy web features, it's nice to use it when available and fallback to something that works when you can't. Probably best just to refer to this Gist. Literally just include that chunk anywhere before you use requestAnimationFrame or cancelAnimationFrame.

Using this, you'll be able to use requestAnimationFrame in literally any browser.

Slightly More Complex Example

I learned about this while making a dumb little demo to learn canvas better:

Check out this Pen!

What would actually be more complex is several animations running at once using this (that still falls back OK). Feel free to link some of that goodness up in the comments if you know of examples.

Comments

  1. You can make your “Simplest possible example” even simpler :)

    function repeatOften() {
      // Do whatever
      requestAnimationFrame(repeatOften);
    }
    repeatOften();
    
    • MaxArt

      Yes, for the sake of simplicity it works, but I wouldn’t recommend to start an animation like that, because it would be rendered in the exact same moment it’s called and not when the browser actually is free, so it misses the point of requestAnimationFrame.

    • Mateusz GawliƄski
      Permalink to comment#

      Or even more simple:

      (function repeatOften() {
          // Do whatever
          requestAnimationFrame(repeatOften);
      })();
      
  2. John

    On the first example, click start more than once. :P

  3. Oh, yeah and we still have to use vendorprefixes for it, but it is a great method. The web is in continous evolution…

    var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
    
    • The polyfill mentioned above handles that, and a few more little things to make sure it all works perfect (like falling back to setTimeout and handling cancellations).

  4. matthew Fowles

    Here is a fork of the first example but have added some code so that if you click buttons more than once it doesn’t break.

    http://cdpn.io/cCoFf

    • matthew Fowles

      Also just realised this demo can be a great way of playing at making patterns out css nth type selectors.

  5. Solomon
    Permalink to comment#

    That’s really nice. I wonder if an image can be in-scripted in it.

    • Matthew Fowles
      Permalink to comment#

      Sure it could be if you work out the pattern of nth squares.

  6. First of all thank you for this really great inovation ! I have some questions that Why request Animation Frame won’t let you alter frame rate? Why is 60fps the default, and why can’t this be changed? Or can it?

  7. I read a tut on paulirish’s blog and he suggests you move the call-yourself of your function to the start of the function to get closer to 60fps when on the setTimeout fallback

    http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/

  8. I’m having trouble with trying to use an animation function that’s a class method. It needs to access other properties and methods from the class, but the context I’m getting is the Window object.

    function MyObj() {}
    function MyObj.prototype.anim = function () {
      console.log(this); // gives the Window object
      requestAnimationFrame(this.anim);
    }
    
    var o = new MyObj();
    var animId = requestAnimationFrame(o.anim);
    

    I’ve tried using call and bind, but haven’t gotten that to work. Any ideas?

    • imma

      guessing it’s no longer relevant, but either of these should work
      var animId = requestAnimationFrame(o.anim.bind(o)); //built-in bind
      or
      var animId = requestAnimationFrame(function(){o.anim()}); //manual bind

  9. George
    Permalink to comment#

    The start-stop demo works awfully in Safari (v5.1.7), poorly in FF(v26) and Opera (v17.0) in my tests.
    It works good only on Chrome(30) and IE(v10).
    SO, I think it is a waste of time to implement it . Just stick to setInterval function, at steps of 16.67ms (60hz).

    Unfortunately the morons behind the browser development and standardization are still left in the technology of the 70’s or earlier when genlock was introduced to synchronize the video cameras with the VCRs and their unbelievable idiocy and sloppiness still affect all of us.

  10. Muhammad Irfan

    Hi Chris, Great lecture about requestanimationframe, i need to know, How to control speed using this function?

    • imma

      I expect the best option is to base your speed off the timestamp parameter it passes into the callback
      Alternately you could use an external setInterval to move things around & just draw them in requestAnimationFrame
      I don’t think you can change how often requestAnimationFrame fires, though perhaps using a monitor with a different frame rate might work but I think 60Hz is universal

  11. You said “recursively calls itself”… But, be careful, because this isn’t recursion as people usually think of it (with the side effects of stack space, etc).

This comment thread is closed. If you have important information to share, you can always contact me.

*May or may not contain any actual "CSS" or "Tricks".