Delivering Consistent Animations with a Design System Library
A few months ago at Intuit my motion designer friend (Brandon Wall) and I (design technologist) wanted to make it easier for developers to implement the motion designs Brandon had created in After Effects. To help them out, and to have an interactive preview for our design team, we built the QuickBooks Animation Library.
Our approach to animation lately has been to use Lottie for more complex storytelling animations, and CSS for almost all UI animation on the web. We previously used GSAP for some animations, but lately for most projects we’ve found we can design around the constraints created by CSS animation.
Inspiration to build a library
In the past, we’ve worked with developers 1 on 1 to share motion specs that included animation curves, timings, and delays. This worked well when building components that were easily adopted by other teams because new teams using the components never even have to think about UI animation. There were a few downsides though:
- QuickBooks has a number of different design & engineering teams and it’s difficult to work with all of them directly
- 3rd party vendors didn’t have easy access to existing animation specs or coded animations
- Motion specs were often created in After Effects or Principle; Adapting them to new projects required specialized design skills
- Motion specs weren’t always available as code; Using them required specialized developer skills
With those considerations in mind, we were inspired by the simplicity of Animate.css and similar animation libraries. There are a number of similar libraries available, but we think sharing our take on them will help contribute to the field since we have a consistent motion aesthetic and are a bit more constrained than the other libraries available. Many existing libraries approach motion design with the philosophy that more motion is better.
How we built it
One thing we really liked about these libraries was the interactive previews, so the first thing we did was include those:
Working in SCSS, we worked backward from some of the existing motion work to systemize how we defined our animations. Here’s the structure of the library in 4 layers:
1. Motion variables. These include values to animate between and common durations, but the animation easing curves are most critical since they contribute much of the character to UI animations.
2. Keyframes. These define the values to animate from and to.
3: Base animations. Built using our motion variables and keyframes.
Note that the entrances use animation-fill-mode
backwards so that an animation delay works properly and we also don’t need to worry about the animation styles after the animation has run. Similarly, the exit animations use animation-fill-mode
forwards so an element will stay hidden even if stays in the DOM.
4: Semantic mappings. To make our UI animations easier to manage and update in the future, we also created semantic mappings so hopefully, our users won’t have to think about choosing the appropriate animation for a modal, flyout, menu, etc. These can be tricky though since we’ve found these terms aren’t always used consistently and new visual styles can create cases where the semantic mapping doesn’t appear as intended.
In future versions, we plan to make the mappings of variables + keyframes to the base animations and then to semantic animations more transparent in the documentation. I’ve already had people view the documentation and ask me: “Which curve is this?”
Options for using the animation library
We started with SCSS mixins so you can add animations without having to add classes to your HTML:
We also provide a CSS file for workflows where adding classes directly is easiest:
Finally, we recently added the option to use the animation library with styled components:
A frontend developer experienced with animation could also just import the motion variables (via SCSS or styled-components) as a starting point for further experimentation. See the usage documentation for more detail.
Warning for CSS minifiers!
One issue we ran into when using CssNano to create a minified version of the CSS is that by default it will rename your keyframes from
c. We’ve added a configuration file so the keyframe names don’t get minified, but be careful if you’re generating your own CSS and it gets minified. This creates some comically bad experiences when combined with other CSS files that also have minified keyframe names:
This is one approach to systematizing animation code for the web. Developers have a wide range of experience with implementing animations, so we’ve mostly focused on making it as easy as possible to drop in the appropriate animation. Onboarding designers and developers is an ongoing process though, so there are a few questions we’re still working on.
- Will we need to provide additional guidance to prevent teams from adding too many animations?
- How can we best encourage teams to default to the appropriate semantic animation when one is available?
- Do we need to provide additional guidance or examples for altering the animations for marketing and single-use applications where we might want different keyframes or more theatrical timing?
- For the QuickBooks platform specifically, how do we best provide training in using react-transition-group and styled-components?
Both of these have some pretty reasonable animations, but in some cases, it feels off to see the same decelerating easing on both entrance and exit animations. Animate.css also does some translations over 100% the height of the element, which can lead to very different distances covered depending on the height of the element being animated.