The modern web of today is filled with sights to behold on every page,
where menus slide in and out, content gently fade into view, and elements
animate around the screen as the user scrolls the page. While CSS3 has
supplanted JavaScript in many cases to help power these rich animations in an
intuitive, well optimized manner, JavaScript will always have a role to play in
more complex scenarios that involve user interaction or non linear logic. It is
because of this that the requestAnimationFrame() method was introduced, to help
us execute animation related JavaScript code that make changes to the user's
screen in an efficient, optimized manner. You've no doubt heard about this
method before, though like many people may not quite understand its benefits or
how to properly use it yet. In this tutorial we'll get you all caught up so you
can finally start taking advantage of requestAnimationFrame() to
perform animations more optimally in your scripts. Let's roll!

Why we need
another hero- requestAnimationFrame

First of all, lets talk about requestAnimationFrame() as an idea
and why we even need such a method. Traditionally to create an animation in
JavaScript, we relied on setTimeout() called recursively or setInterval() to
repeatedly execute some code to make changes to an element frame by frame, such
as once every 50 milliseconds:

While the above code is logically sound, its actual execution is
far from perfect. The problem with using setTmeout/setInterval for executing
code that changes something on the screen is twofold.

What we specify as the delay (ie: 50 milliseconds) inside
these functions are often times not honoured due to changes in user system
resources at the time, leading to inconsistent delay intervals between
animation frames.

Even worse, using setTimeout() or setInterval() to
continuously make changes to the user's screen often induces "layout
thrashing", the browser version of cardiac arrest where it is forced to
perform unnecessary reflows of the page before the user's screen is
physically able to display the changes. This is bad -very bad- due to the
taxing nature of page reflows, especially on mobile devices where the
problem is most apparent, with janky page loads and battery drains. An
iPhone or two have even caught fire as a result (just a joke Apple, no law
suits please)!

requestAnimationFrame()
to the rescue

It is for the above reasons requestAnimationFrame() was
introduced. The method in a nutshell allows you to execute code on the next
available screen repaint, taking the guess work out of getting in sync with the
user's browser and hardware readiness to make changes to the screen. When we
call requestAnimationFrame() repeatedly to create an animation, we are assured
that our animation code is called when the user's computer is actually
ready to make changes to the screen each time, resulting in a smoother, more
efficient animation. Furthermore, code called via requestAnimationFrame() and
running inside background tabs in your browser are either paused or slowed down
significantly (to 2 frames per second or less) automatically to further save
user system resources- there's no point in running an animation that isn't being
seen is there?

So requestAnimationFrame() should be used in place of setTimeout/
setInterval for animations, but how exactly do we go about doing that? Before we
get to that, lets look at browser support first. requestAnimationFrame() today
enjoys
wide
adoption amongst modern browsers- IE10+, FF11+, Chrome, and Safari etc. For
some older versions of these browsers, a vendor prefix is needed in front of the
method name to work. Even on browsers that don't support this method in any
incarnation, we can simply fallback in those cases to setTimeout() instead to
call the code after a certain delay instead. The following code creates a
universal rrequestAnimationFrame() and its counterpart cancelAnimationFrame()
function that works in the maximum number of browsers, with a fallback built in:

For the fallback setTimeout() code, notice the delay being set
at 1000/60, or around 16.7 milliseconds. This value simulates how often the real
requestAnimationFrame()
will typically be called by the browser each time it's invoked based on the
typical user's screen refresh rate of 60 frames per second.

Understanding
and using requestAnimationFrame()

The syntax for requestAnimationFrame is very straightforward:

requestAnimationFrame(callback)

We enter a callback function containing the code we wish to run,
and requestAnimationFrame() will run it when the screen is ready to accept the
next screen repaint. Some noteworthy details:

The callback function is automatically passed a timestamp
indicating the precise time requestAnimationFrame() was called.

requestAnimationFrame() returns a non 0 integer that can be
passed into its nemesis counterpart cancelAnimationFrame() to cancel a requestAnimationFrame()
call

Here's an example of calling requestAnimationFrame() once to
move a DIV just 5 pixels from its original location on the screen:

The above code is very similar to using setTimeout() to run the
same code, except instead of after the user defined delay, the code is called on
the next available screen repaint, typically around 16.7 milliseconds based on a
typical screen refresh rate of 60fps. The exact number may fluctuate and frankly
doesn't matter; what's important to realize is that the browser will now
intelligently invoke our code only when it is ready to accept changes to the
screen, not before.

Calling requestAnimationFrame() once is pretty meaningless most
of the time. The magic happens when we call it "recursively" to construct
the desired animation frame by frame, with each frame being called only when the
browser is ready for it. This this how requestAnimationFrame() becomes superior
to setTimeout or setInterval when it comes to handling animation related code
efficiently. Lets rewrite our initial example of moving a DIV across the screen
5 pixels at a time using requestAnimationFrame():

The above code shows the basic blueprint for using requestAnimationFrame()
to create an animation, by defining your animation code inside a function, then
inside this function calling itself recursively through requestAnimationFrame()
to produce each frame of our animation. To kick start the animation, we make a
call to requestAnimationFrame() outside the animation function with that
function as the parameter.

Animation
over time in requestAnimationFrame()

So it's simple enough to repeatedly call an animation function
using requestAnimationFrame(), but most animations are much more
finicky,
having to stop at some point after a certain objective has been achieved over a
certain amount of time. Take our example of moving the DIV above; in a real life
scenario, what we probably want to do is move the DIV 400 pixels to the right
over a time of say 2 seconds. To do this with requestAnimationFrame(), we can
take advantage of the timestamp parameter that's passed into the callback
function. Lets see how this works now, by retooling our DIV moving code above so
it moves the DIV a certain distance over a certain amount of time:

Just before the animation runs, we set the startime variable
to the current time using either requestAnimationFrame's
timestamp parameter, or if requestAnimationFrame isn't supported, a less
precise new Date().getTime() instead. The former is a value automatically
passed in as the first parameter of the callback function of requestAnimationFrame
that contains a highly accurate representation of the current time in
milliseconds (accurate to 5 microseconds). This lets us know when the
animation started running.

Inside the animation function moveit(), we capture the
current time of the current "frame" using variable timestamp. We use the
difference between that and the animation starttime to figure out at what
"point" along the animation we're currently at, and change the DIV's
position accordingly out of the total distance (ie: 400px).

Slowing down
or cancelling requestAnimationFrame()

The standard requestAnimationFrame runs at around 60fps under
ideal conditions (or once every 16.7ms), in sync with the refresh rate of the
typical monitor. If your animation requires a different frames per second (up to
60 fps) or simply doesn't require that high a level of refresh rate, you can slow it
down by calling requestAnimationFrame inside setTimeout(). That way, you get the
desired frame rate while reaping the benefits of requestAnimationFrame:

In this version of moving a DIV horizontally, we're
throttling the frames per second to roughly 20, by calling requestAnimationFrame
inside setTimeout() each time.

- Cancelling requestAnimationFrame()

Just like with setTimeout/ setInterval, you can cancel a
requestAnimationFrame call, and in identical fashion as well.
requestAnimationFrame when called returns a non 0 integer that can be captured
inside a variable and passed into its nemesis counterpart cancelAnimationFrame()
to stop it from being invoked again. The following logs the timestamp parameter
value of requestAnimationFrame for two seconds, using cancelAnimationFrame to stop the former:

Conclusion

As you can see, requestAnimationFrame() is actually very simple
in concept and execution, once you understand its purpose and common
patterns. A lot of frameworks such as
jQuery 3.0 utilize requestAnimationFrame() internally for all
animation related functions, though it's definitely better to understand how
this method works natively so you can take advantage of it in any JavaScript
environment.