On UI Animations

Shu Ding, 05/27/2020

Thanks Paco for bringing up this great topic, and creating the outline of this article, while we brainstorming the animation part of our design system. Here're some personal notes that I think worth writing down.

Establish Common Transition Values and Specify Them as Design Tokens

This (using CSS animation variables) will be very helpful for most of our use cases. I personally prefer ease with a small duration (~200ms) as the transition, but we can define our own easing function too.

Define What Transitions Should Be Used in What Context

Generally we can divide all transitions into 2 groups:

A. Style (opacity, color, background, shadow, border, transform, etc.)

When transitioning a style, the animation should be subtle and it serves the functionality of noticing the user that something has appeared, disappeared, or changed, or simply showing that some element is interactable.

This covers most components such as popover, tooltip, menu, button, link, modal, ... and in this case, we should simply use the CSS variables defined based on the varying property.

B. Layout (top, left, bottom, right, height, width, etc.)

When transitioning the layout, we usually want to show the logic of the UI implicitly to the user, so they will have the sense of.

Things with a fixed layout (so the animation will have a fixed timing and range). They should be tweaked case by case, e.g.: feedback input and toast.

For things which we can't predict the size and position (they change based on the dynamic content), e.g.: file tree, collapse, show more, drawer..., there're 2 difficulties:

  • It's not allowed to use CSS to animate a size from 0 to auto. So the target size has to be measured (getBoundingClientRect) before the actual animation happens. That makes it harder to implement correctly.
  • Need to handle window resizing events as well, since the target size can change.

In this case, we should use spring animations (e.g.: react-spring, react-motion) with ResizeObserver to measure the size dynamically, which is a better practice in the sense of both design and engineering.

When Is No Animation Desirable?

  • Keep all the animation variables in one place, so we can have the ability to toggle them via one single class .reduce-motion in the future.
  • For toolbar menus or submenus, when hover and moving between items we don't want the popover to fade-in or fade-out frequently. User should be focused on the content, not the animation. And the menu should be visually continuous, like stripe.com or just disable the animation like what macOS does.
  • Functionality first. For very common components like tooltip and menu, we should try to reduce the animation as much as possible: they don't provide much info but can be annoying. I think that's why macOS' menu has only fade-out transition, so the content will be shown instantly when user needs it. Contrary, Material Design has too many useless animations IMO.
  • If the animation slows down the website a lot, we don't want the animation. Instead we should look for alternatives like video or canvas animation.