8.5 CSS animations

A set sequence of CSS rules

We’ve just seen how CSS transitions are just a way to animate CSS properties between a starting state, and an end state.

So CSS transitions are specific kind of animations, where:

  • there’s only 2 states: start and end
  • the animation doesn’t loop
  • the intermediate states are only controlled by the timing function

Well what if you want:

  • to have control over the intermediate states?
  • to make an animation loop?
  • different animations on the same element?
  • to animate a specific property only halfway through the animation?
  • to simulate different timing functions for different properties?

CSS animations allow all of this, and more.

CSS animations are like mini movies where you are the director giving out instructions (CSS rules) to your actors (HTML elements) for different scenes (keyframes).

Animation properties

Like the transition property, animation is a shorthand property for several others:

  • name: the animation’s name
  • duration: how long the transition lasts
  • timing-function: how the intermediate states are calculated
  • delay: to start the animation after a certain amount of time
  • iteration-count: how many times the animation should be performed
  • direction: if the animation should be reversed or not
  • fill-mode: what styles are applied before the animation starts and after it ends

Quick example

To animate a loading button, you could write a bouncing animation:

@keyframes bouncing{
  0%  { bottom: 0; box-shadow: 0 0 5px rgba(0,0,0,0.5);}
  100%{ bottom: 50px; box-shadow: 0 50px 50px rgba(0,0,0,0.1);}

.loading-button{ animation: bouncing 0.5s cubic-bezier(0.1,0.25,0.1,1) 0s infinite alternate both;}

You first need to write the actual bouncing animation using keyframes and name it bouncing. Then you can use that animation by applying it to .loading-button.

I used the shorthand animation property, and included all options:

  • name: bouncing (matches the keyframes name)
  • duration: 0.5s (half a second)
  • timing-function: cubic-bezier(0.1,0.25,0.1,1)
  • delay: 0s (no delay)
  • iteration-count: infinite (plays indefinitely)
  • direction: alternate (goes back and forth)
  • fill-mode: both


Before applying animations to HTML elements, you need to write animations using keyframes. Basically, keyframes are each intermediate step in an animation. They are defined using percentages:

  • 0% is the first step of the animation
  • 50% is the step halfway through the animation
  • 100% is the last step

You can also use the keywords from and to instead of 0% and 100% respectively.

You can define as many keyframes as you want, like 33%, 4% or even 29.86%. In practice, you’ll only write a few.

Each keyframe is CSS rule, meaning that you can write CSS properties just like usual.

To define an animation, just write the keyword @keyframes followed by its name:

@keyframes around {
  0%  { left: 0; top: 0;}
  25% { left: 240px; top: 0;}
  50% { left: 240px; top: 140px;}
  75% { left: 0; top: 140px;}
  100%{ left: 0; top: 0;}
p{ animation: around 4s linear infinite;}


Notice how the start 0% and the end 100% have the same CSS rules. This ensures that the animation loops perfectly. Because the iteration count is set to infinite, the animation will go from 0% to 100%, and then back to 0% instantly and indefinitely.


The animation’s name is used at least twice:

  • when writing the animation using @keyframes
  • when using the animation using the animation-name property (or with the animation shorthand)
@keyframes whatever{
  /* ... */

.selector{ animation-name: whatever;}

Like CSS class names, animation names can only include:

  • letters (a-z)
  • numbers (0-9)
  • underscores (_)
  • dashes (-)

It can not start with a number or two dashes.


Just like transition durations, animation durations can be set in seconds 1s or milliseconds 200ms.

.selector{ animation-duration: 0.5s;}

It defaults to 0s, which means no animation at all.


Just like transition timing functions, animation timing functions can use keywords like linear, ease-out, or be defined using custom cubic bezier functions.

.selector{ animation-timing-function: ease-in-out;}

It defaults to ease.

Because CSS animations use keyframes, you can set a linear timing function and simulate a specific cubic bezier curve by defining a lot of very specific keyframes. Check out Bounce.js to generate advanced animations.


Just like transition delays, animation delays can be set in seconds 1s or milliseconds 200ms.

It defaults to 0s, which means no delay at all.

It’s useful when triggering multiple animations in sequence.

.a,.b,.c{ animation: bouncing 1s;}
.b{ animation-delay: 0.25s;}
.c{ animation-delay: 0.5s;}


By default, animations are only played once (value of 1). You can set 3 types of values:

  • integers like 2 or 3
  • non-integers like 0.5 which will play only half the animation
  • the keyword infinite which will repeat the animation indefinitely
.selector{ animation-iteration-count: infinite;}


The animation’s direction defines in which order the keyframes are read.

  • normal: starts at 0%, ends at 100%, starts at 0% again
  • reverse: starts at 100%, ends at 0%, starts at 100% again
  • alternate: starts at 0%, goes to 100%, goes to 0%
  • alternate-reverse: starts at 100%, goes to 0%, goes to 100%

It’s easier to visualise if the animation’s iteration count is set to infinite.

Normal: 0% --> 100%

Reverse: 100% --> 0%

Alternate: 0% <--> 100%

Alternate reverse: 100% <--> 0%


An animation’s fill mode defines what happens before the animation starts and after it ends.

When you define keyframes you define CSS rules to be applied at different steps of the animation. Now, these CSS rules can clash with the ones already applied on the elements being animated.

The fill mode allows to tell the browser if the animation’s styles should also be applied outside of the animation.

Let’s imagine a button that is:

  • red by default
  • turns blue at the start of the animation
  • ends up green when the animation is over
animation-fill-mode Before the animation Start of the animation End of the animation After the animation
none Default Start End Default
forwards Default Start End End
backwards Start Start End Default
both Start Start End End

1. Before the animation 2. During the animation 3. After the animation

None: the animation styles do not affect the default style

Default red From blue to green Back to red again

Forwards: the last styles applied at the end of the animation are retained afterwards

Default red From blue to green Remains green

Backwards: the animation's styles will already be applied before the animation actually starts

Already blue From blue to green Back to red again

Both: the styles are applied before and after the animation plays

Already blue From blue to green Remains green

Back to top

Learn CSS with my ebook

This ebook is a step by step guide in which I teach you how to build your own personal webpage from scratch, line by line, with HTML5, CSS3, and even JS.

CSS in 44 minutes book cover
Get it now