CSS Animations are a great way to animate CSS properties from one to another. While we can use transitions to perform single movements, animations give us much finer control.

Some common properties we might animate include colors (color& background-color), and numbers such as height & width.

Check out the full list of animatable CSS properties.

Creating an animation

An animation consists of both a style rule which describes the animation, and a set of keyframes indicating the start and end states of the that style. We can also optionally add waypoints.

Let’s see an example:

Our animation is defined using the animation property & it’s movement with @keyframes, like so:

.ball {
  border-radius: 50%;
  width: 200px;
  height: 200px;
  background-color: pink;
  border: 2px solid #000;
  animation: bounce 1s infinite alternate;
@keyframes bounce {
  from {
    margin-top: 0;
  to {
    margin-top: -250px;

Our element moves between the differing start and end positions (in this case we’ve adjusted the margin).


There are a number of sub-properties we can work with, to give us more control:

  • animation-name: Specifies the name of the @keyframes at-rule, which describes the animation’s keyframes.
  • animation-duration: Sets the length of time that an animation should take to complete one cycle.
  • animation-timing-function: Specifies the timing of the animation; or how it ‘flows’ through the keyframes.
  • animation-delay: Sets a delay between the time the element is loaded and the beginning of the animation.
  • animation-direction: Sets the direction of the animation after the cycle.
  • animation-iteration-count: Sets the number of times the animation should repeat. We can use infinite to repeat the animation indefinitely.
  • animation-fill-mode: Sets which values are applied before & after the animation executes. For example, you can set the animation to remain on screen upon completion, or revert to its start state.
  • animation-play-state: Lets you pause and resume the animation sequence.

Let’s see another example:

Here we use the following values:

.ball {   
  animation-name: grow;
  animation-duration: 2s; 
  animation-timing-function: ease-out; 
  animation-delay: 0;
  animation-direction: alternate;
  animation-iteration-count: infinite;
  animation-fill-mode: none;
  animation-play-state: running;  

We could simplify this using the animation shortcode:

.ball {   

In our example, the keyframes are set like so:

@keyframes grow {
  0% {
    transform: scale(.5);
    background-color: yellow;
    border-radius: 100%;
  50% {
    background-color: purple;
  100% {
    transform: scale(1.5);
    background-color: pink;

As mentioned, we can use waypoints with @keyframes to further control the animation. They are set as percentages, with 0% being the beginning of the animation and 100% the end.

In our example, we have our initial (0%) state set to scale .5 & yellow, then 50% of the way through we change the color to purple, and at 100% it has scaled to 1.5 and turned pink.

Working with multiple animations

Multiple animations can be declared on a selector, using comma-separated values.

In the following example, we set the colors to swap with one keyframe rule, and we move it side to side with another:

.ball {
    colorswap 2s linear infinite alternate, 
    movement 6s ease-out infinite alternate;

A note on prefixing

Modern browsers now widely support animation properties, so there is no real need to worry about vendor prefixing. In the case where we want to support old browsers. We’d need to ensure we have the appropriate prefixes, like so:

.element {
  -webkit-animation: YOUR-KEYFRAME-NAME 1s infinite;
  -moz-animation:    YOUR-KEYFRAME-NAME 1s infinite;
  -o-animation:      YOUR-KEYFRAME-NAME 1s infinite;
  animation:         YOUR-KEYFRAME-NAME 1s infinite;
@-webkit-keyframes YOUR-KEYFRAME-NAME {
  0%   { /* ... */ }
  100% { /* ... */ }
@-moz-keyframes YOUR-KEYFRAME-NAME {
  0%   { /* ... */ }
  100% { /* ... */ }
@-o-keyframes YOUR-KEYFRAME-NAME {
  0%   { /* ... */ }
  100% { /* ... */ }
  0%   { /* ... */ }
  100% { /* ... */ }

Related Posts: