Bringing Pages to Life with the Web Animations API

Share this article

5 images stacked on top of each other

This article is by guest author Dudley Storey. SitePoint guest posts aim to bring you engaging content from prominent writers and speakers of the JavaScript community.

One API to Rule Them All

Animation on the web has long been divided into four disparate camps:

  • CSS transitions and animations are very performant and provide keyframing, but are also time-consuming to build, and provide only basic start-and-end control in CSS and JavaScript. This has tended to relegate them to simple UI response animations, loops, and page load animations.
  • SMIL (Synchronized Multimedia Integration Language) is very powerful, but it’s also syntax-heavy and has incomplete browser support. It’s also limited to controlling elements solely inside the context of SVG.
  • JavaScript offers direct control of elements, but has no understanding of designer-friendly functions like keyframes or easing, and lacks the native optimization and performance of CSS. Canvas API animation is wonderful, but still lacks an understanding of animation fundamentals, and can’t animate arbitrary DOM elements.
  • JavaScript animation frameworks like Greensock attempt to pave over the traditional deficits of JavaScript when it comes to animation, but have all the associated drawbacks of frameworks: page load, performance, and learning a new syntax.

The Web Animations API seeks to integrate the best features of all of these into a single, unified specification, while eliminating the drawbacks, creating a native understanding of keyframes, easing, and element control in JavaScript, with the same on-screen performance as CSS. With core components of the specification now supported in Chrome and Firefox, and development either announced or underway in other browsers, including Safari and Edge, together with the availability of a robust polyfill, it’s time to give the Web Animations API serious consideration for bringing web pages to life.

Keyframes in JavaScript

Let’s take one of the simplest possible examples of a keyframe animation: moving a red ball element from one side of the page to the other. Regardless of which technique we use, the element will be the same:

<div id="redball"></div>

As will the initial CSS:

body {
  margin: 0;
  background: #000;
  overflow: hidden;
  min-height: 100vh;
}

#redball {
  background: red;
  width: 30vmin;
  height: 30vmin;
  border-radius: 50%;
}

I’ve used vmin units so that the element always remains symmetrical while responding to the size of the viewport.

In CSS, moving the ball from one side of the page to the other would require something like the following:

@keyframes moveBall {
  from {
    transform: translateX(-20vw);
  }
  to {
    transform: translateX(100vw);
  }
}

This animation would be called from the declaration for the red ball element:

#redball { 
  animation: moveBall 3s infinite;
}

The result, shown in Codepen:

See the Pen Basic CSS Red Ball Animation by SitePoint (@SitePoint) on CodePen.

There are a few things to note about the animation at this point, including the fact that easing (speeding up at the beginning and slowing down at the end) is automatically built in.

Enter the Web Animations API

Keeping the HTML and initial styles, let’s remove the CSS animation and substitute JavaScript that uses the Web Animation API to accomplish the same thing:

var moveBall = document.getElementById('redball').animate([{
  transform: 'translateX(-20vw)'
}, {
  transform: 'translateX(100vw)'
}], {
  duration: 3000,
  iterations: Infinity,
  easing: 'ease'
});

You can see that the animation takes most of the same syntax as CSS, but represents it as an object with an array representing the keyframes. We don’t have to explicitly declare to or from in the keyframes – JavaScript will automatically distribute the keyframes evenly for us, although declaration is also entirely possible.

The animation won’t play yet; just like in CSS, we have to call it:

moveBall.play();

The keyframe part of the syntax will become even easier in future browsers, as aspects of the CSS transform syntax that were previously values become available as properties:

translateX: -20vw;

This change to the specification is already available in Chrome Canary, but it be a year or two before the new syntax is available in all modern browsers.

There are a few other things to note about the script:

  • JavaScript takes animation timing in milliseconds, rather than the standard CSS seconds (milliseconds is also available in CSS, so long as ms is suffixed to a timing value).
  • The Web Animations API specifies the number of iterations as iterations, rather than the CSS property of interation-count (when it is defined separately); the keyword is Infinity (with a capital I) for the number of repetitions, rather than CSS’s infinite.
  • In the Web Animations API the default easing is linear, so in our demo we specify ease the default value for CSS Animations.

The result is functionally equivalent to the CSS animation.

See the Pen Basic Red Ball Anim in Web Animation API by SitePoint (@SitePoint) on CodePen.

Of course, duplicating a CSS animation like this in JavaScript doesn’t really use the dynamism of the scripting language nearly to its maximum ability; to demonstrate that, we’ll create a much more fully-featured animation.

Dealing Images

Stack of images animated using the Web Animations API

Some time ago I was interesting in creating an animation that dealt a series of images onto the web page, like flicking playing cards onto a table. Writing individual animations for each card in traditional CSS would have taken a great deal of time, and would have always delivered the same result. Instead, I used the Web Animations API as the perfect tool for the job.

Progressive Cards

We want the images to be seen regardless of whether JavaScript or the Web Animations API is enabled or not, so we start by adding a series of images to the page:

<div class="shuffle expose">
  <img src="bridgefog.jpg" alt>
  <img src="daisyface.jpg" alt>
  <img src="drowninghand.jpg" alt>
  <img src="firefigure.jpg" alt>
  <img src="shellhand.jpg" alt>
  <img src="waterfeet.jpg" alt>
</div>

I’ve left the alt values of the images blank to keep the code clear; in the production version, they would be filled with descriptions. The photographs are by .tafo., used under a Creative Commons Attribution-NoDerivs 2.0 Generic license.

We can add a little CSS to bring the images on with animation if the no-JavaScript condition is still true:

@keyframes reveal {
  to {
    opacity: 1;
  }
}
.shuffle {
  min-height: 100vh;
  position: relative;
}
.shuffle img {
  width: 33%;
  opacity: 0;
}
.expose img {
  animation: reveal 1s forwards;
}

The individual image delivery could be delayed with:

.expose img:nth-child(1) { animation-delay: 1s; }
.expose img:nth-child(2) { animation-delay: 2s; }
.expose img:nth-child(3) { animation-delay: 3s; }

Naturally, these declarations could be automated with Sass or another preprocessor.

The images will have a border if the parent element has a class of webanim, which will be applied with JavaScript:

div.webanim img {
  border: 1.4vw solid #eee;
}

The JavaScript

We’ll add the script to the end of the page. I’ll need several random values in the animation, so I’ll create a function to produce those:

function getRandom(min, max) {
  return Math.random() * (max - min) + min;
}

I’ll then gather the image container and all the images inside them, together with setting an incrementor variable:

var imgContainer = document.querySelector(".expose"),
    imgSeq = document.querySelectorAll(".shuffle img"),
    i = 1;

Then, I’ll remove the expose class (leaving the images at an opacity of 0 and unanimated (since the CSS animation only works if the container has an expose class:

imgContainer.classList.remove("expose");
imgContainer.classList.add("webanim");

The webanim class places the images with a border.

The bulk of the script takes place in a forEach loop inside a function. I’ll call the function once I’m assured that all the image data is loaded (as opposed to the image nodes merely appearing in the DOM) using the excellent imagesLoaded script by David DeSandro:

function racknstack() {
  Array.prototype.forEach.call(imgSeq, function(photo) {
    setTimeout(function() {
      photo.style.position = "absolute";
      photo.style.width = getRandom(33, 45) + "%";
      photo.style.left = getRandom(-5, 65) + "%";
      photo.style.top = getRandom(-6, 60) + "vh";
      var animate = photo.animate([{
        opacity: '0',
        transform: 'rotate(' + getRandom(-12, 12) + 'deg) scale(1.2)',
        boxShadow: '0 0 12px 12px rgba(0,0,0,.3)'
      }, {
        opacity: '1',
        transform: 'rotate(' + getRandom(-8, 8) + 'deg)',
        boxShadow: '0 0 6px 6px rgba(0,0,0,.3)'
      }], {
        duration: 2000,
        fill: 'forwards'
      });
    }, 1800 * i)
    i++;
  })
}

As before, we must call the function to start things off:

imagesLoaded(imgSeq, racknstack);

The result:

See the Pen Random Stacked Images w/ WebAnim API & Progressive JS by SitePoint (@SitePoint) on CodePen.

In turn, the function:

  • sets each image to an absolute position;
  • generates a random width for the image (as a percentage, so the image remains fluid and responsive)
  • generates a random position for the image (including a possible negative position, meaning that it may appear slightly off the edge of the viewport)
  • animates the photo using the Web Animation API. The keyframes fade the image in from 0 to solid opacity, while rotating the image

The forwards fill is necessary because we want the images to stay in their end state after the animation has completed.

From Strength to Strength

Development on the Web Animation API continues apace:

Conclusion

As you can see, the Web Animations API allows us to move from the specific, declarative, step-by-step nature of CSS animations to the dynamic, imperative approach of JavaScript that allows for expressive, random, performant animation.

I’d love to see your explorations in the Web Animation API, especially in production sites: let me know in the comments below!

Frequently Asked Questions about Web Animations API

What is the Web Animations API?

The Web Animations API is a powerful tool that allows developers to create and control animations directly in JavaScript, without the need for CSS. It provides a common language for browsers and developers to describe animations, making it easier to create complex animations and transitions. The API is designed to be efficient, flexible, and easy to use, making it a great choice for any web developer looking to add some flair to their websites.

How does the Web Animations API differ from CSS animations?

While both the Web Animations API and CSS animations allow you to create animations, they do so in different ways. CSS animations are created using CSS syntax and are controlled through CSS properties. On the other hand, the Web Animations API allows you to create and control animations directly in JavaScript. This gives you more control and flexibility over your animations, as you can use all the power of JavaScript to manipulate them.

How do I start using the Web Animations API?

To start using the Web Animations API, you first need to create an animation. This is done using the Element.animate() method, which takes two arguments: a keyframes object and an options object. The keyframes object describes the animation’s keyframes, while the options object specifies the animation’s timing properties.

Can I control the playback of an animation with the Web Animations API?

Yes, the Web Animations API provides several methods for controlling the playback of an animation. These include play(), pause(), cancel(), and finish(). These methods allow you to start, pause, cancel, and finish an animation, respectively.

What are the benefits of using the Web Animations API?

The Web Animations API offers several benefits over other animation methods. It provides a common language for describing animations, making it easier to create complex animations. It also allows you to control animations directly in JavaScript, giving you more control and flexibility. Additionally, the API is designed to be efficient and performant, ensuring your animations run smoothly.

Is the Web Animations API supported in all browsers?

The Web Animations API is supported in most modern browsers, including Chrome, Firefox, and Safari. However, it is not supported in Internet Explorer. You can check the current level of support on websites like Can I Use.

Can I use the Web Animations API to animate SVGs?

Yes, the Web Animations API can be used to animate SVGs. This allows you to create complex animations with SVGs, which can be a powerful tool for creating interactive graphics and visualizations.

How can I chain animations with the Web Animations API?

You can chain animations using the finished promise of an animation. This promise is resolved when the animation finishes, allowing you to start a new animation immediately after the previous one finishes.

Can I use the Web Animations API with React?

Yes, you can use the Web Animations API with React. However, as React has its own system for handling updates to the DOM, you may need to use refs to access the DOM nodes you want to animate.

What are some resources for learning more about the Web Animations API?

There are many resources available for learning more about the Web Animations API. The Mozilla Developer Network (MDN) has extensive documentation on the API, and there are numerous tutorials and articles available online. Additionally, the W3C specification for the API provides a detailed and technical overview of its features and functionality.

Dudley StoreyDudley Storey
View Author

Dudley Storey has been making web pages for almost has long as there has been a web to create them on. A writer, designer and teacher of web design & development, he is the upcoming author of a book on SVG that will published by O'Reilly in early 2017.

CSS Animationshtml5 apisjameshWeb Animation API
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week