Meaningful motion helps make our product easy for everyone and tells our brand's story. It helps people make sense of space and navigate digital interfaces.

Also known as:
Motion designTransitions

AnchorNeed to know

  • Aim for a fast time to first interaction of 300ms or less with primary content or data.
  • Test designs with 100 animated instances shown at once. Test designs with one animation repeated 100 times.
  • Use animation on the 1 primary call to action.
  • Use more user-initiated than system-initiated animation.
  • Use our palette of animation styles, easing functions, and timing variables.

To keep in mind

The "wow" factor of motion wins deals. We're hard wired to notice movement and pay attention to it.

Animation Design Tokens

Use our animation design tokens to ensure consistency for animation durations and easing timing functions:

$kz-animation-easing-function-ease-in-out: cubic-bezier(
$kz-animation-easing-function-ease-in: cubic-bezier(0.55, 0.085, 0.68, 0.53);
$kz-animation-easing-function-ease-out: cubic-bezier(0.25, 0.46, 0.45, 0.94);
$kz-animation-easing-function-linear: linear;
$kz-animation-easing-function-bounce-in: cubic-bezier(
$kz-animation-easing-function-bounce-out: cubic-bezier(
$kz-animation-easing-function-bounce-in-out: cubic-bezier(
$kz-animation-duration-instant: 0ms;
$kz-animation-duration-immediate: 100ms;
$kz-animation-duration-rapid: 200ms;
$kz-animation-duration-fast: 300ms;
$kz-animation-duration-slow: 400ms;
$kz-animation-duration-deliberate: 700ms;
$animation-easing-function-ease-in-out: var(
cubic-bezier(0.455, 0.03, 0.515, 0.955)
$animation-easing-function-ease-in-out-id: --animation-easing-function-ease-in-out;
$animation-easing-function-ease-in: var(
cubic-bezier(0.55, 0.085, 0.68, 0.53)
$animation-easing-function-ease-in-id: --animation-easing-function-ease-in;
$animation-easing-function-ease-out: var(
cubic-bezier(0.25, 0.46, 0.45, 0.94)
$animation-easing-function-ease-out-id: --animation-easing-function-ease-out;
$animation-easing-function-linear: var(
$animation-easing-function-linear-id: --animation-easing-function-linear;
$animation-easing-function-bounce-in: var(
cubic-bezier(0.485, 0.155, 0.24, 1.245)
$animation-easing-function-bounce-in-id: --animation-easing-function-bounce-in;
$animation-easing-function-bounce-out: var(
cubic-bezier(0.485, 0.155, 0.515, 0.845)
$animation-easing-function-bounce-out-id: --animation-easing-function-bounce-out;
$animation-easing-function-bounce-in-out: var(
cubic-bezier(0.76, -0.245, 0.24, 1.245)
$animation-easing-function-bounce-in-out-id: --animation-easing-function-bounce-in-out;
$animation-duration-instant: var(--animation-duration-instant, 0ms);
$animation-duration-instant-id: --animation-duration-instant;
$animation-duration-immediate: var(--animation-duration-immediate, 100ms);
$animation-duration-immediate-id: --animation-duration-immediate;
$animation-duration-rapid: var(--animation-duration-rapid, 200ms);
$animation-duration-rapid-id: --animation-duration-rapid;
$animation-duration-fast: var(--animation-duration-fast, 300ms);
$animation-duration-fast-id: --animation-duration-fast;
$animation-duration-slow: var(--animation-duration-slow, 400ms);
$animation-duration-slow-id: --animation-duration-slow;
$animation-duration-deliberate: var(--animation-duration-deliberate, 700ms);
$animation-duration-deliberate-id: --animation-duration-deliberate;

When to use and when not to use

When to use
  • Aim for fast time to first interaction and consider if the stylized entrance feels slower than instantly loading content.
  • Use consistent direction and movement in relation to local environment to reinforce context and UI metaphors.
  • For entrances, exits, and decorations, animation style is so subtle that you can’t put your finger on it.
  • Avoid bounces or overshoots. We make exceptions when the bounce or overshoot is related to the animation effect or behavior itself, such as our emphasized growing "Take action" pill.
When not to use
  • Content rules. Draw attention to important content and data, not to interface controls.
  • Avoid keeping people from their content with time-consuming or showy entrances.
  • Avoid contradicting movement that breaks UI metaphors, such as an element entering with a fade and slide and exiting with a scale.
  • Avoid sharp, noticeable entrances that draw attention away from the content to the animation itself.
  • Avoid excessively bouncy animations that tarnish our trustworthy brand.

Meaningful motion

We use animation purposefully to:

  • Provide our customers, human resource leaders, with visual cues for direction and focus.
  • Create a consistent experiential 'feel' across the product.
  • Indicate interaction affordances.
  • Achieve context shifting.
  • Affect our audience's perception of time and indicate something is happening.
  • To set a tone that matches our brand.
  • Celebrate our customers' milestones.
  • Give feedback, especially reassurances.
  • Create an emotional, engaging experience with delight.

Categories of animation

  • Choreographed entrances and exits
  • Stylized entrances and exits
  • Loading and progress
  • Show and hide
  • Cause and effect
  • Ambient information
  • Demonstrations
  • Interaction feedback

Designing animations

Animate once and one hundred times

Every microinteraction animation works well for the first time and the hundredth time.

  • Test 100 animated instances shown at once.
  • Test a single animation repeated 100 times.

Aim for a fast time to first interaction

Aim for a fast time to first interaction of 300ms or less with primary content or data. Supplementary content may have a delay and arrive after the first 300ms.

What is too much animation?

1. Use 1 primary call to action

If there are continually running animations on a page, the motion draws the user’s attention to the most important thing they need to be doing.

2. Use more user-initiated animation than system-initiated

We are more adventurous with the amount and size of user-initiated animation than system-initiated. If people want to keep clicking a button because of its fun animations, go wild; for looping animations constantly running on a page, cut back!

Note: consider player controls to pause, stop or hide animations. See also: Pause, Stop, Hide: Understanding Success Criterion 2.2.2 from the Web Content Accessibility Guidelines.

3. Minimize browser jank for silky smooth rendering

To minimize browser jank (stuttering or choppiness), we test our animations to ensure they keep up at 60 frames per second, including in old browsers and devices. If they cannot keep up, that might be a sign of too much animation.

This topic can be a little bit controversial and usually involves a comparison between CSS and JS animations. We want to ensure the implementation of performant animations is as easy as possible, so we have opted for a “CSS-first” approach to animations.

Stagger separate items and synchronize connected items

Separate, individual items that are meaningfully different from each other can move separately, with staggered entrances and exits. For example, navigation items that link to wildly different content can enter one after another.

Connected items move together as a single body. We synchronize movement of groups of closely related items.

Placeholder loading skeletons predict content

Placeholder loading skeletons fill the space that its future content will occupy when it's loaded.

  • Give people an idea of what’s about to come and what’s happening (it's currently loading).
  • Be subtle, because it’s not a real, interactive interface.
  • Be flexible to an unknown number of items or shape of data being loaded. This might be indicated either through composition to suggest the shape of what will arrive, or through repeatable elements.
  • When content arrives, it does not move around sharply compared to the placeholder loading skeleton.
  • We don’t currently use gradients in our branding aesthetic, so for ‘shimmering’ skeletons we opt for opacity changes rather than animated gradients.

Choreographed entrances provide a red carpet experience

A choreographed entrance or orchestrated entrance introduces elements in a sequence, potentially with overlapping action. We “stage” the most important content.

A stylized entrance applies to a single element that may be standalone or part of a choreographed entrance.

Choreographed, stylized entrances focus attention through movement and reinforce our branding and design.

Choreographed entrances are reserved for “red carpet” or “grand unveiling” experiences, such as first use, onboarding, demos, showcasing new features, or landing pages rather than frequently visited pages.

In contrast to a placeholder loading skeleton, choreographed or stylized entrances don’t care how long content takes to load. For example, the whole page might be loaded already, but we only reveal each section with a fade as the person scrolls down the page. A single stylized entrance may mask and replace a short loading spinner.

Animation & Transition Presets

Here are some pre-defined CSS transitions and animations that are ready to use. All animations and transitions have accompanying mixins that let you define customized behavior for duration, delay, and direction.

Animations are not transitions. Although they can appear visually the same, the key difference is that animations are keyframe-driven and will play immediately, unless controlled with CSS properties e.g. animation-play-state. Transitions need to be “triggered”, usually by adding a class to the element or on user interaction e.g. hover.



Tip: If you are prototyping, the animation presets are useful. As they are keyframe-driven, they do not need to be “triggered” like transitions, and will play by adding the animation class to the element.



Sass mixins

We have Sass mixins and animation presets. To use them, import the animation styles into your Sass file.

Our animation helpers have been heavily built upon Zurb’s Motion UI. Most of the mixins are aliased versions from the motion-ui library. This lets us expand upon them and potentially remove this dependency without breaking our animation API.



To use any of the animation presets, define a class and include the mixin. All preset animation mixins are prefixed with ca-animation-.

Fade@include ca-animation-fade
Pop@include ca-animation-pop
Pulsate@include ca-animation-pulsate
Scale Fade@include ca-animation-scale-fade
Slide Fade@include ca-animation-slide-fade
state (in or out)State to transition to. (Default: in)
duration (Keyword)Length (speed) of the transition. (Default: $ca-duration-slow)
delay (Duration)Delay in seconds or milliseconds before the transition starts. (Default: null)


To use any of the transition presets, define a class and include the mixin. All preset transition mixins are prefixed with ca-transition-.

Transition Presets

Note: Transitions need to be “triggered” by adding .ca-enter-active or .ca-exit-active classes.

Fade@include ca-transition-fade
Scale Fade@include ca-transition-scale-fade
Slide Fade@include ca-transition-slide-fade
state (in or out)State to transition to. (Default: in)
duration (Keyword)Length (speed) of the transition. (Default: $ca-duration-slow)
delay (Duration)Delay in seconds or milliseconds before the transition starts. (Default: null)

Sequencing Animations

Sequencing animations with CSS/Sass can be cumbersome. To reduce verbosity and complexity, we have a couple of mixins that will help orchestrate more complex animation sequences.

@import "~@kaizen/component-library/styles/animation";
@import "~@kaizen/design-tokens/sass/animation";
$duration: $kz-animation-duration-deliberate; // 700ms
$delay: -$kz-animation-duration-slow; // -400ms (stagger effect)
@include ca-series {
.spin-1 {
@include ca-queue($duration, $delay, pulsate);
.spin-2 {
@include ca-queue($duration, $delay, pulsate);
.spin-3 {
@include ca-queue($duration, 0, pulsate);

Note: This mixin will only work with animation keyframe functions e.g. pop and pulsate.

durationLength (speed) of the transition
delayDelay in seconds or milliseconds before starting the next transition
functionone or more animation keyframe functions e.g. pulsate, pop, fade...

Technical considerations

Rendering performance

For fast 60 frames-per-second animations, you can cheaply animate:

  • Opacity
  • Translate (move the position)
  • Scale (pixel scaling)
  • Rotate

For animating other properties, you might use will-change so the browser can set up appropriate optimizations ahead of time before the element is actually changed.

Note: opacity, translation, scale, and rotate do not affect the “box” the item takes up on the page. You can use transform: scale or transform: translate, but the content will still take up the same space on the page as if no transform had been applied.

Animate collapsing height

There are different approaches to achieve expand and collapse animations with different trade-offs:

  • transform: scaleY() – fast, but items below do not move up.
  • transform: translateY() – fast, but items below do not move up.
  • height: 0 – the box shrinks height, so content inside is reflowed (can look awkward, or generate scrollbars, etc.).
  • margin-top: – the box stays the same size, but shifts up and consumes less space, so items below shift up. (This can result in overlapping content above if you are not careful!) Useful if you want to “slide behind” another element or if you time it so the shift up happens in conjunction with a fade out such that it has mostly faded out by the time it would overlap with other content.

Reduce motion

Animation can cause accessibility issues, such as motion sickness in people with vestibular disorders. In components and bespoke animations or data visualizations, we can use the prefers-reduced-motion CSS media feature or matchMedia in JavaScript where appropriate to reduce motion as users choose. This is particularly important for long or large animations, such as parallax effects, or anything that may be startling. For example:

.animation {
  animation: pulsate $kz-var-animation-duration-fast $kz-var-animation-easing-function-ease-in-out infinite both;

@media (prefers-reduced-motion: reduce) {
  .animation {
    animation: none;

External links

Here are some examples of existing design systems that use motion: