I’ve learnt a lot about animations on the web in the past year since joining the product team at Qwilr. I’ve spent a lot of it thinking about how to distill what I’ve found hard about designing and building animations (or taking animations from a prototype).

For the most part, I think there’s nothing like practice for getting good at these things, and I’ll reiterate that here: the best way of getting more comfortable with animation tooling is to do more of it, either through your work or in your spare time.

The hard parts were:

  • Understanding the primary principle of CSS animations
  • Learning concrete examples of animations using a framework
  • Sifting through the sheer number of animation opportunities (choice paradox)

In this post, I’m going to go through these one by one.

Primary principle of animation on the web

When working with native animation tooling on the web, the key principle is that basic animations require:

  1. Setup of how the animation works (what we animate)
  2. A trigger for the animation to fire (when we animate)

This is honestly a truism and probably redundant to say at this point, but it’s the guiding principle behind how most animation utilities for common web frameworks like React and Angular.

A concrete example in React

We’ll start with an example of a panel in React that “springs” open when the page loads.

This example makes use of the react-transition-group npm package, which is the canonical maintained CSS animation library for React.

Generally you’ll have some CSS like this:

.panel {
  // Basic setup of the panel
  width: 300px;
  height: 600px;
  background: white;
  border: 1px solid black;
}

// This class is applied when the panel first exists in the DOM
.panel--entering {
  // Initial state
  opacity: 0;
  transform: scale(0.94);
  // Setup of the animation to be run
  transition: opacity 1s linear, transform 1s linear;
}

// This class is applied after the panel exists in the DOM (after a reflow has been applied)
.panel--entering-active {
  // End state
  opacity: 1;
  transform: scale(1);
}

And some React code like this:

import React from "react";
import { CSSTransition } from "react-transition-group";

const Panel = () => (
  <CSSTransition
    mountOnEnter
    in={true}
    // Note the timeout here needs to be at the
    // same length as the transition.
    timeout={1000}
    classNames="panel-"
  >
    {/* Note that you'll need a key here, but its arbitrary */}
    <div key="panel" className="panel">
      Hello world, this is my panel
    </div>
  </CSSTransition>
);

And when you load the page, it should spring into action.

Note that here we’ve:

  • Added our initial state on entering
  • Set up how to animate the properties
  • Added our final state on entering-active

Most animation libraries will do some magic to ensure those classes occur at the right times (involving “reflows”), and they’ll vary a bit but not a lot.

For example, AngularJS’s ng-animate will inspect the keyframes applied to your class and then automatically figure out the timeout to apply, whereas with React’s transition group we need to manually specify our own timeouts (as in the above example).

If you want more details on this specific library, I recommend you look at their docs.

Common hooks for animations

This is the final “hard” bit – the near infinite opportunities for animations is often the blocker to getting started. Unless you have formal training in animation, it’s quite hard to know where to “start” from a design perspective.

I found that working with an experienced interaction designer has helped me greatly, and for the most part I think having someone onboard to help is the best way.

If you don’t, I have a few recommendations.

State transitions

If you’re talking about transitioning a component from one state to another (for example on hover, or on drag over), the best properties to animate are things like:

  • opacity
  • box shadow
  • color and background-color

Mount / unmount

If you’re looking at adding animations to something that’s appearing / disappearing from a page, consider:

  • transform: scale
  • transform: translateX/translateY
  • opacity

Make it opt-out-able

The one thing I’d recommend keeping in mind as you start animating your world is that animations can make an experience more delightful, but not for everyone.

  • Some users may dislike animations
  • Some users may suffer from conditions like vertigo that are exacerbated by animations

In those cases, remember to allow opt-out for those users’ browsers with the prefers-reduced-motion media query.