A Comparison of Animation Technologies

Avatar of Sarah Drasner
Sarah Drasner on (Updated on )

The question I am asked most frequently: what animation tool do you recommend?

Having worked with a slew of them, I can tell you there is no right answer. It’s a complicated question and complicated answer. This post serves to clarify what to use, and when, to get you working with the right tool for the job.

If you’re here for React, we’ve got you covered! Jump down to the React section below and we’ll break down what to use and how to use it.

There’s no possible way to go over every single animation library around, so I’m going to stick with the ones that I’ve either used or that interest me. Please keep in mind that these are my recommendations based on my own experiences, and the web has a lot of grey area, so you may have a different experience or opinion. That’s OK.

Native Animation

Before we talk about any libraries, let’s go over some native animation implementations. Most libraries are using native animation technologies under the hood anyway, so the more that you know about these, the more you’ll be able to negotiate what is happening when it becomes abstracted.

CSS

CSS remains one of my favorite ways to animate. I’ve been using it for years and continue to be a fan due to its legibility and excellent performance. CSS animations make it possible to transition between different states using a set of keyframes.

Pros:

  • You don’t need an external library.
  • The performance is great, especially if you do things that are inherently hardware accelerated (offloaded to the GPU). Here’s an article about the properties that will help you do so.
  • Preprocessors (like Sass or Less) allow you to create variables (for things like easing functions or timings) that you’d like to remain consistent, along with :nth-child pseudo classes in functions to produce staggering effects.
  • You can listen for onAnimationEnd and some other animation hooks with native JavaScript.
  • Motion along a path is coming down the pipeline which will be rad.
  • It is easy to use for responsive development because you can modify your animation with media queries.

Cons:

  • The bezier easings can be a bit restrictive. With only two handles to shape the bezier, you can’t produce some complex physics effects that are nice for realistic motion (but not necessary very often).
  • If you go beyond chaining three animations in a row, I suggest moving to JavaScript. Sequencing in CSS becomes complex with delays and you end up having to do a lot of recalculation if you adjust timing. Check out this Pen from Val Head that illustrates what I mean. Staggers are also easier to write in JavaScript. You can hook into the native JavaScript events I mentioned earlier to work around this, but then you’re switching contexts between languages which isn’t ideal, either. Long, complex, sequential animations are easier to write and read in JavaScript.
  • The support for motion along a path isn’t quite there yet. You can vote on support for Firefox here. Voting for support in Safari, as far as I can gather, is a little more individual. I registered to fill out a bug report and requested motion path module in CSS as a feature.
  • CSS + SVG animation has some strange quirkiness in behavior. One example is that in Safari browsers, opacity and transforms combined can fail or have strange effects. Another is that the spec’s definition of transformation origin, when applied sequentially, can appear in a non-intuitive fashion. It’s the way that the spec is written. Hopefully SVG 2 will help out with this but for now, CSS and SVG on mobile sometimes requires strange hacks to get right.

requestAnimationFrame

requestAnimationFrame (rAF) is a native method available on the window object in JavaScript. It’s really wonderful because under the hood, it figures out what the appropriate frame rate is for your animation in whatever environment you’re in, and only pushes it to that level. For instance, when you’re on mobile, it won’t use as high a framerate as on desktop. It also stops running when a tab is inactive, to keep from using resources unnecessarily. For this reason,
requestAnimationFrame is a really performant way of animating, and most of the libraries we’ll cover use it internally. requestAnimationFrame works in a similar fashion to recursion, before it draws the next frame in a sequence, it executes the logic, and then calls itself again to keep going. That might sound a little complex, but what it really means is that you have a series of commands that are constantly running, so it will interpolate how the intermediary steps are rendered for you very nicely.

Canvas

Canvas is great to get those pixels moving! So many of the cool things you see on CodePen are made by canvas magicians. Like its name suggests, canvas offers a visual space scripting, in which you can create complex drawings and interaction, all with high performance rendering. We’re working with pixels here, which means they are raster (as opposed to vector).

Pros:

  • Since we aren’t moving things around in the DOM, but rather a blob of pixels, you can make a ton of complex things happen without weighing down performance.
  • Canvas is really nice with interaction. You’re already in JavaScript which offers a lot of control without switching contexts.
  • The performance is very good. Especially considering what you can make.
  • The sky’s the limit on what you want to create.

Cons:

  • It’s difficult to make accessible. You’d have to use something like React to create a DOM for you, which Flipboard managed to do a little while ago, though in their case study it seemed they had more work to do. There’s probably an opportunity there, though, if you’re interested in taking up the charge.
  • I find it pretty unintuitive to make responsive. By this, I don’t mean making a small version work on the phone, because that it does well. I mean moving and shifting and reorganizing content based on the viewport. I’m sure there are some really great devs out there who do it easily, but I would say it’s not terribly straightforward.
  • It’s not retina-ready. Unlike SVG animation which is resolution-independent, most of the canvas animations I see are not crisp on retina displays.
  • It can be difficult to debug. When what you are building breaks, it breaks by showing nothing, unlike animating in the DOM, where things are still there but just behaving weirdly.

SMIL

SMIL is the native SVG animation specification. It allows you to move, morph and even interact with SVGs directly within the SVG DOM. There are a ton of pros and cons to working with SMIL, but the biggest con will lead me to omit it entirely: it’s losing support. Here’s a post I wrote on how to transfer over to better-supported techniques.

Web Animations API

The Web Animations API is native JavaScript that allows you to create more complex sequential animations without loading any external scripts. Or will, anyway, when support grows. For now you’ll probably need a polyfill. This native API was created as a backfill from all of the great libraries and work that people were already making with JavaScript on the web. This is part of a movement to align the performance of CSS animations and the flexibility of sequencing in JavaScript under one roof. If you’re interested in hearing more, there is a ShopTalk episode all about it.

Pros:

  • Sequencing is easy and super legible. Just check out this example from Dan Wilson which compares CSS keyframes and the web animation API.
  • Performance seems to be on track to being very good. I haven’t tested this myself well yet but plan to. (You can and should be running your own performance tests as well).

Cons:

  • Support is not great right now. It’s also still changing a bit so while the spec is moving I would be cautious about running it in a production environment.
  • There are still a lot of things about the timeline in GSAP (which we’ll be covering in a moment) that are more powerful. The important ones for me are the cross-browser stability for SVG and the ability to animate large swaths of sequences in a line of code.

WebGL

There are some extraordinary things you can do with WebGL. If anything is blowing your socks off, there’s a good chance it was made with WebGL. What it’s really good at is interactive and 3D effects. Check out some of these demos. Technically it uses canvas, but I like making the distinction because, I don’t know, names are cool when they work to identify slight variance.

Pros:

  • Amazing visual effects
  • Three dimensions means a whole new world for interaction
  • Hardware-accelerated
  • Possibilities for VR

Cons:

  • Tougher to learn than the other native animations we’ve covered thus far. The first two animations I made I thought weren’t working because I had the camera pointed the wrong way (womp womp). There are also less really good articles and books explaining how to work with it than the other technologies I’ve mentioned thus far, but they’re growing.
  • Hard to make responsive. Most websites I’ve seen that use WebGL fall back to a “please view this site on desktop” screen.

External Libraries

GreenSock (GSAP)

GreenSock is far and away my favorite library to work with. Please understand that this bias comes from working, playing around with, and bumping my head badly on a lot of different animation tooling so when I give my strong endorsement, it’s through blood, sweat and tears. I especially like it for SVG. The GreenSock Animation API has almost too many cool benefits to list here without missing something, but they have both docs and forums you can explore.

Pros:

  • It’s extraordinarily performant for something that’s not native. As in, performs just as well, which is major big deal.
  • The sequencing tools (like timeline) are as easy to read as they are to write. It’s very simple to adjust timing, have multiple things fire at once with relative labels, and even speed your animations up or down with one line of code.
  • They have a ton of other plugins if you want to do fancy things like animate text, morph SVGs, or draw paths.
  • Their motion along a path in the bezier-plugin has the longest tail of support available.
  • It solves SVG cross-browser woes. Thank goodness for this one. Especially for mobile. There’s some good info about that in this post they wrote.
  • They offer really nice, very realistic eases.
  • Since you can tween any two integers, you can do cool stuff like animate SVG filters for some awesome effects, and even works in canvas. Sky’s the limit on what you can animate.
  • GSAP is the only animation library, including the native SMIL, that lets you morph path data with an uneven amount of points. This has opened new opportunities for motion and movement. (If you’d like to it in action, go the logo at the top of this page on desktop and click the orange bit in the dash.)

Cons:

  • You have to pay for licensing if you’re re-selling your product to multiple users (apps and paid-access sites). That’s probably not most cases. I’ll also put in that supporting work on this isn’t the worst thing in the world.
  • As with any external library, you have to watch which versions you are using in production. When new versions come out, upgrading will involve some testing (like any library). You’ll also need to consider the size of the library.

VelocityJS

VelocityJS offers a lot of the sequencing that GreenSock does, but without a lot of the bells and whistles. I no longer really use Velocity due to the cons below. Velocity’s syntax looks a bit like jQuery, so if you’ve already been using jQuery, it will be familiar.

Pros:

  • Chaining a lot of animations is a lot easier than CSS.
  • For refinements in eases there are step-eases where you can pass an array.
  • The documentation is pretty nice so it’s easy to learn and get up and going.

Cons:

  • The performance isn’t great. Despite some claims to the contrary, when I ran my own tests I found that it didn’t really hold up. I suggest you run your own, though, as the web is always moving and this post is frozen in time.
  • GSAP has more to offer, for performance and cross-browser stability without more weight. I would also say that jQuery used to lose performance tests but that might have changed since their RAF adoptions, so Velocity isn’t bad by any means, but it loses out in comparison.
  • From what I can tell, it’s not actively being maintained anymore. I’ve heard that Julian Shapiro has passed the project off to someone else, so it may make a resurgence sometime in the future.

jQuery

jQuery isn’t solely an animation library, but it has animation methods and a ton of people use it, so I thought I would cover it.

Pros:

  • A lot of sites already have it loaded, so it’s usually readily available.
  • The syntax is really easy to read and write.
  • They recently moved over to requestAnimationFrame, so in versions 3.0.0 and greater, the performance will be better than before.

Cons:

  • Versions earlier than 3.0.0 performance is not great and not recommended. I haven’t tested this in a very formal way, but aside from looking at repaints and painting in Chrome DevTools, you can also see it with your eyes.
  • Animations aren’t supported on SVG in any version.
  • jQuery is limited to the DOM, unlike tools like GSAP which work on anything.

Snap.svg

A lot of people think of Snap as being an animation library, but it was never intended to be one. I was going to run performance benchmarks on Snap, but even Dmitri Baranovskiy (the incredibly smart and talented author of Snap.svg, and it’s predecessor, Rafael), says here on the SVG Immersion Podcast that it’s not the correct tool for this, and in a message to me said:

Just a note: Snap is not an animation library and I always suggest to use it with GSAP when you need a serious animation.

That said, jQuery is not great with SVG, though they do now support class operations. If I need to do any DOM manipulation with SVG, Snap is really awesome for this.

A library called SnapFoo was released recently, and it extends Snap’s realm to animation. I haven’t played with it myself yet, but it looks pretty cool and is worth a go. If you try it, report back or comment below!

Mo.js

This is a library by an awesome fellow that goes by LegoMushroom. He’s an extremely talented animator, and has already made some great demos for this library that have me really excited. This library is still in beta it’s getting very close to being released now. I wrote an introductory guide to working with it here if you’re interested in learning more.

Pros

  • There are things like shapes, bursts, and swirls, which are really easy to work with
    and spin things up for you- so you don’t need to be the world’s best or most creative illustrator to get something nice going.
  • Mo.js offers some of the best and most beautiful tooling on the web, including
    players, timelines, and custom path creators. This in and of itself is one of the most compelling reasons to use it
  • There are a few different ways to animate- one is an object, one is plotting a
    change over the course of an ease- so you can decide which way you feel more comfortable.

Cons

  • It doesn’t yet offer the ability to use an SVG as a parent for the custom shapes, (I
    believe LegoMushroom is working on this), so working with coordinate systems and scaling for responsive is less intuitive and harder to make work on mobile. This is a fairly advanced technique, though, so you might not need it.
  • It doesn’t correct cross-browser behavior like GreenSock does yet, which means
    you might need to write hacks like you do with CSS. He mentioned he’s also working on this as well.

Three.js

Three.js is a beautiful three dimensional animation tool! Check out some of these examples. I haven’t worked with this a lot so I don’t feel comfortable reporting on it, but I plan to and will update the post when I know more. People usually talk about this and the native WebGL in tandem.

Bodymovin’

Bodymovin’ meant for building animations in Adobe After Effects that you can export easily to SVG and JavaScript. Some of the demos are really impressive. I don’t work with it because I really like building things from scratch with code (so this defeats the purpose for me), but if you’re more of a designer than a developer, this tool would probably be really great for you. The only con I see to that part is that if you need to change it later, you’d have to re-export it. That might be a weird workflow. Also, the outputted code is usually kind of gross, but I haven’t seen that affect the performance too much in the case of Bodymovin’, so it’s probably fine.

React-Specific Workflows

Before we talk about React, let’s cover why we have to treat animations in React differently at all. DOM stands for Document Object Model. It’s how we create a structured document with objects, the nodes of which we talk about as a tree. React interacts with a virtual DOM, which is unlike the native browser DOM implementation, it’s an abstraction.

React uses a virtual DOM number of reasons, the most compelling of which is the ability to figure out what’s changed and update only the pieces it needs to. This abstraction comes at a price, and some of the old tricks that you’re used working with will give you trouble in a React environment. jQuery, for instance, will not play nice with React, being that it’s primary function is to interact and manipulate with the browser’s native DOM. I’ve even seen some strange CSS race conditions. Here are some of my recommendations for nice animations in a React workflow.

React-Motion

React-Motion is a very popular way to animate in React, and the community has adopted it over the old ReactCSSTransitionGroup that used to be most frequently used. I like it a lot, but there are some keys points to working with it that if you don’t get, will have you banging your head.

React-Motion is pretty similar to game-based animation, where you give an element mass and physics and send it on it’s way, and it gets there when it gets there. What this means is that you aren’t specifying an amount of time like you do with CSS or any other traditional web-based sequential motion. This is a pretty different way of thinking about animation. This can mean that the motion has the ability to look really realistic which can be very beautiful. But UIs have different requirements than games, so working with this can get tricky. Let’s say you have two things that have to fire independently and get there at the same time that are different. It can be tough to line them up exactly.

Up until recently, there was no sequencing available. Just last week, Cheng Lou added in onRest, which allows for this kind of callback workflow. It’s still not easy to write a loop without writing an infinite loop (bad). You might not need that but I thought I would call it out. As an FYI to the performance-sensitive, it uses re-rendering.

Pros:

  • The animation can look really beautiful and realistic, and the spring options are nice.
  • The staggering effect is pretty nice. It is also available in most JS libraries, but this one is created based on the last motion, not by duplicating the last one, so there are some nice motion possibilities.
  • The addition of onRest is a big deal. It allows for some sequencing that wasn’t available before, so if you look at the demos, you’re not even seeing all it has to offer yet.
  • I’d consider this currently the animation tool that plays with React the best.

Cons:

  • It’s not super plug-and-play like some other libraries or native are, which means you end up writing quite a bit more code. Some people like this about it, some people don’t. It’s not kind on beginners this way, though.
  • The sequencing, due to the complex nature of the code, are not as straightforward or legible as some of the alternatives.
  • onRest doesn’t yet work for staggering parameters.

GSAP in React

GreenSock has so much to offer that it’s still worth using in a React environment. This is particularly true for more complex sequencing, which is where React-Motion doesn’t offer a slim solution and GreenSock shines. It takes a bit more finessing than usual, and some things that should work and do with the DOM, don’t in React. That said, I’ve gotten React and GSAP to play nice a few different ways now so here’s how I do it.

  1. Hook into the native React component lifecycle methods.
    Here’s how I do that. When I want it to fire right off the bat, I use componentDidMount.
  2. Create a function that has a timeline and then call that function within something you use for interaction. I can have an inline event handler like onClick(), and within the custom function I have for it, I’ll call another function that has a timeline within it. In a jQuery or vanilla JS setup, I would pause the timeline initially and hit replay, but I don’t have to do that here.
  3. Here’s a nice post that Chang Wang wrote about how to hook them into ReactTransitionGroup(), which is a pretty cool way of doing it.
  4. You can use a library like React-Gsap-Enhancer. I haven’t worked with this one myself too much but there are really sweet demos. One of these is a fork of one of my own demos and I will say, though, that when I looked at the code it seemed much more verbose that what I wrote. I’m not sure if that’s due to the library or React itself, or their style.

CSS in React

CSS animations has had a bit of a resurgence lately likely because it’s the easiest way to go for animations in React. I like working with them for little things like UI/UX interactions. I have seen them behave a little funny if you try to chain things using delays. Other than that, they’re pretty great, especially for small UI adjustments. In terms of real-world animations on the web, sometimes CSS is Occam’s Razor.

Conclusion

This is an opinion post by someone who feverishly works with animation all the time and this is what I’ve gathered from pure brute force of working with these technologies a lot. My opinions might not be shared by everyone, and that’s fine. I don’t have any particular reason to hold allegiance with any technology except, as a developer, considering its versatility, performance, and ease of use. Hopefully, this information can save you some time.