Animations

Animation is a great way to highlight interactive elements, and add interest and fun to your designs. In this module, find out how to add and control animation effects with CSS.

Sometimes you see little helpers on interfaces that provide some helpful information about the section they're in when you click them. These often have a pulsing animation to subtly let you know that the information is there and should be interacted with. This module shows you how to create those helpers, and other animations, using CSS.

Pulsing icons are one way to make sure your users pay attention to important information.

You can use CSS to set an animation sequence with keyframes. These sequences can be basic, one-state animations or complex, time-based sequences.

What is a keyframe?

In most animation tools, keyframes are the mechanism you use to assign animation states to timestamps on a timeline.

For example, here's a timeline for the pulsing "helper" dot. The animation runs for 1 second and has 2 states.

The states of the pulser animation over the 1 second timeframe
The states of the pulsing animation.

There's a specific point where each of these animation states start and end. You map these out on the timeline with keyframes.

The same diagram as before, but this time, with keyframes
The pulsing animation with keyframes.

@keyframes

Browser Support

  • Chrome: 43.
  • Edge: 12.
  • Firefox: 16.
  • Safari: 9.

Source

CSS @keyframes are based on the same concept as animation keyframes.

Here's an example with two states:

@keyframes my-animation {
  from {
    transform: translateY(20px);
  }
  to {
    transform: translateY(0px);
  }
}

The first important part is the custom identifier (custom-ident), the name of the keyframes rule. The identifier in this example is my-animation. The custom identifier works like a function name, letting you reference the keyframes rule elsewhere in your CSS code.

Inside the keyframes rule, from and to are keywords that represent 0% and 100%, which are the start and end of the animation. You could re-create the same rule like this:

@keyframes my-animation {
    0% {
        transform: translateY(20px);
    }
    100% {
        transform: translateY(0px);
    }
}

You can add as many positions as you like along the timeframe. In the pulsing helper example, there are two states that translate to two keyframes. This means you have two positions inside your keyframes rule to represent the changes for each of these keyframes.

@keyframes pulse {
  0% {
    opacity: 0;
  }
  50% {
    transform: scale(1.4);
    opacity: 0.4;
  }
}
Try editing the pulse rule to see how the animation changes.

The animation properties

Browser Support

  • Chrome: 43.
  • Edge: 12.
  • Firefox: 16.
  • Safari: 9.

Source

To use your @keyframes in a CSS rule, you can either define various animation properties individually, or use the animation shorthand property.

animation-duration

Browser Support

  • Chrome: 43.
  • Edge: 12.
  • Firefox: 16.
  • Safari: 9.

Source

.my-element {
    animation-duration: 10s;
}

The animation-duration property defines how long the @keyframes timeline should be as a time value. It defaults to 0 seconds, which means the animation still runs, but it'll be too quick for you to see. You can't use negative time values.

animation-timing-function

Browser Support

  • Chrome: 43.
  • Edge: 12.
  • Firefox: 16.
  • Safari: 9.

Source

To help recreate natural motion in animation, you can use timing functions that calculate the speed of an animation at each point. Calculated values are often curved, making the animation run at variable speeds over the course of animation-duration, and making the element appear to bounce if the browser calculates a value beyond those defined in @keyframes.

There are several keywords available as presets in CSS, which are used as the value for animation-timing-function: linear, ease, ease-in, ease-out, ease-in-out.

.my-element {
    animation-timing-function: ease-in-out;
}
Try changing which timing function the animation uses.

Easing function values appear to curve because easing is calculated using a Bézier curve, a type of function used to model velocity. Each of the timing function keywords, such as ease, references a predefined Bézier curve. In CSS, you can define a Bézier curve directly using the cubic-bezier() function, which accepts four number values: x1, y1, x2, y2.

.my-element {
    animation-timing-function: cubic-bezier(.42, 0, .58, 1);
}

These values plot each part of the curve along the X and Y axis.

A Bézier curve on a progression vs time chart
An example Bézier curve.

Understanding Bézier curves is complicated. Visual tools, such as this generator by Lea Verou, are very helpful.

The steps easing function

Sometimes you might want to take more granular control of your animation by moving in intervals instead of along a curve. The steps() easing function lets you break the timeline into defined intervals of equal duration.

.my-element {
    animation-timing-function: steps(10, end);
}

The first argument is the number steps. If there are the same number of keyframes as steps, each keyframe plays in sequence for the exact duration of its step, with no transition between states. If there are fewer keyframes than steps, the browser adds steps between keyframes depending on the second argument.

The second argument is the direction. If it's set to end, which is the default, the steps finish at the end of your timeline. If it's set to start, the first step of your animation completes as soon as it starts, which means it ends one step earlier than end.

Compare the animations with and without steps.

animation-iteration-count

Browser Support

  • Chrome: 43.
  • Edge: 12.
  • Firefox: 16.
  • Safari: 9.

Source

.my-element {
    animation-iteration-count: 10;
}

The animation-iteration-count property defines how many times the @keyframes timeline should run during the animation. By default, this is 1, which means that the animation stops when it reaches the end of your timeline. This value can't be a negative number.

Try changing the iteration count for this animation.

To make your animation loop, set the iteration count to infinite. This is how the pulsing animation from the start of this lesson works.

The pulsing animation iterates infinitely.

animation-direction

Browser Support

  • Chrome: 43.
  • Edge: 12.
  • Firefox: 16.
  • Safari: 9.

Source

.my-element {
    animation-direction: reverse;
}

You can set which direction the timeline runs over your keyframes with animation-direction, which takes the following values:

  • normal: the default value, which is forward.
  • reverse: runs backward over your timeline.
  • alternate: for each animation iteration, the timeline alternates between running forward and running backward.
  • alternate-reverse: Like alternate, but the animation starts with the timeline running backward.
Try changing the animation direction.

animation-delay

Browser Support

  • Chrome: 43.
  • Edge: 12.
  • Firefox: 16.
  • Safari: 9.

Source

.my-element {
    animation-delay: 5s;
}

The animation-delay property defines how long the browser waits before starting the animation. Like the animation-duration property, this takes a time value.

Unlike animation-duration, you can define animation-delay as a negative value, which makes the animation start at the corresponding point in your timeline. For example, if your animation is 10 seconds long and you set animation-delay to -5s, the animation starts from halfway through your timeline.

Try changing the animation delay.

animation-play-state

Browser Support

  • Chrome: 43.
  • Edge: 12.
  • Firefox: 16.
  • Safari: 9.

Source

.my-element:hover {
    animation-play-state: paused;
}

The animation-play-state property lets you play and pause the animation. The default value is running. If you set it to paused, the animation pauses.

Hold your cursor over the animated element to pause the animation.

animation-fill-mode

Browser Support

  • Chrome: 43.
  • Edge: 12.
  • Firefox: 16.
  • Safari: 9.

Source

The animation-fill-mode property defines which values in your @keyframes timeline persist before the animation starts or after it ends. The default value is none, which means that when the animation is complete, the values in your timeline are discarded. Other options include:

  • forwards: The last keyframe persists, based on the animation direction.
  • backwards: The first keyframe persists, based on the animation direction.
  • both: Both the first and last keyframes persist.
Try changing the fill mode.

The animation shorthand

Instead of defining each property separately, you can define them in an animation shorthand, which lets you define the animation properties in the following order:

  1. animation-name
  2. animation-duration
  3. animation-timing-function
  4. animation-delay
  5. animation-iteration-count
  6. animation-direction
  7. animation-fill-mode
  8. animation-play-state
.my-element {
    animation: my-animation 10s ease-in-out 1s infinite forwards forwards running;
}

Considerations when working with animation

Users can set their operating system to prefer reduced motion when interacting with applications and websites. You can detect this preference using the prefers-reduced-motion media query:

@media (prefers-reduced-motion) {
  .my-autoplaying-animation {
    animation-play-state: paused;
  }
}

This isn't necessarily a preference for no animation. It's a preference for less animation, especially less unexpected animation. You can learn more about this preference and overall performance in our animation guide.

Try an example of reduced animation.

Check your understanding

Test your knowledge of animations

Is the name or custom identifier of a @keyframes animation case sensitive?

No
Yes

The keywords from and to are the same as:

0% and 100%.
0 and 1
start and end.

The animation-timing-function is also commonly known as:

Delay
Dynamic timing
Easing

What is the minimum number of keyframes required inside a @keyframes animation?

3
1
2
4