CSS Animation: How it works from transitions to animations

CSS3 Animations

CSS animation is definitely the next big step in CSS. Absolutely amazing things can be done with this. It is literally up to your imagination, as you’ll come to realize if you don’t already understand how CSS animations work. HTML5 and javascript continues to replacing what Flash was previously used for, and similarly CSS continues to replace functionality javascript was used to provide. In this article we’re going to cover the CSS animation basics and make sure we’ve learnt it well enough to add it to our development-toolbox.

So, what’s the difference between the Transition property and the Animation property?

There are two basic differences:

  1. The first major difference is that transitions only have a ‘to’ and ‘from’ state. Transitions also only effect once a pseudo class (such as :hover, :focus, :checked, etc) is triggered or removed.
  2. The second notable difference between animations and transitions are @keyframes. Transitions only have two @keyframes (the ‘to’ and ‘from’ states), but animations can have an endless number of @keyframes. The keyframe positions are set with percentage values. You could make a ball spin and bounce up and down with only few lines of CSS (Sort of. Since you’ll have to do everything multiple times with vendor prefixes, the CSS gets quite a bit longer).

Animation syntax

The animation property and keyframes go hand in hand. The animation property’s ‘values’ are the element-to-be-animated’s options and the keyframes are the actions it should follow.

A simpler way to put it is:

Animation: How to animate – duration, speed, etc.
Keyframes: The properties to animate – From/To.

The following animation property is shorthand for the various CSS properties which will be covered later in this section.

[code type=”css”]
#element { animation: name duration timing-function delay iteration-count direction; }

@keyframes name {
0% { property: value1; } //Start of animation duration
35% { property: value2; } //35% through the animation duration
100% { property: value3; } //End of animation duration


The name of the animation. This value links the animation properties to the keyframes. This value is required, without this the keyframes can’t be referenced.


The time it takes for the animation to complete in seconds.


Supported timing-function keywords are: linear, ease, ease-in, ease-in-out, ease-out, step-start, step-end. The cubic-bezier() CSS function is supported by animation-timing-function and can be used to create custom timing-functions.

If left out, this property defaults to ease.


The amount of time, in seconds, waited before the animation begins after the animation has been applied to the element.

If left out, this property defaults to 0s.


The amount of times the animation should run. Negative values are treated as 1 and fraction values play that fraction of that animation. For example 1.5 will play through the animation 1 time and stop halfway through the second iteration. “infinite” does what you’d imagine, it doesn’t stop the animation.

If left out, this property defaults to 1.


The direction of the animation. This property has 4 values: normal, alternate, reverse, alternate-reverse.

The “normal” state would play through the keyframes from the lowest percentage to the highest. This property can be set to “reverse” where it will play from 100% down to 0%.

“alternate” runs the animation in reverse every second iteration, so the animation goes from 0% to 100% the first time and then from 100% to 0% the second time and repeats that pattern. This is property gives the effect that the animation doesn’t restart.

“reverse” runs the keyframes in reverse, for example it begins at 100% and ends at 0%.

Lastly, “alternate-reverse” begins at 100% and reverses every second iteration.

If left out, this property defaults to ‘normal’.

CSS Keyframes

Along with the animation-name, keyframes are the most important aspects of CSS animations. Keyframes are the animation instructions.

Percentage values are used to indicate the point at which the values of a keyframe should be achieved. The “from” keyword references 0% and the “to” keyword references 100%. Functionally the following is identical:

[code type=”css”]
@keyframes example {
0% { bottom: -90px; right: -40px; }
100% { bottom: -90px; right: -40px; }
@keyframes example {
from { bottom: -90px; right: -40px; }
to { bottom: -90px; right: -40px; }
Quick demonstration based on the previously covered properties

In the above example I’ve made use of:

  1. animation-name
  2. animation-duration
  3. animation-timing-function
  4. animation-iteration-count

The 4 “ball” keyframes are telling the element to animate through each of the 4 keyframes within 6 seconds, while making use of a the boring ‘ol linear timing-function and to do this indefinitely.

As you can see, the keyframes syntax is similar to the media query syntax (And SCSS!) – which most people have been exposed to. Hopefully that makes you feel more at home!

That’s really all there is to it. Let’s go over a more detailed tutorial to make this even more digestible.

Simple tutorial

First we have to come up with a cool animation idea. I’m a big fan of Paul Irish (and you should be too) so I’m going to do some sort of animation involving him.

I’ve taken this image and cut out the arm quite badly, so I have two images. The plan is to layer the arm on top of the larger image and animate it.
First we need to define the html

[code type=”html”]
<div id="paul">
<img class="arm" src="img/paul-arm.png" alt="" />

Next, the CSS

[code type=”css”]
#paul {
background: url(../img/paul-bg.jpg) no-repeat left top;
height: 450px;
margin: 0 auto;
overflow: hidden;
width: 600px;
position: relative;
#paul .arm {
animation: pumping-iron 2s ease-out alternate infinite;
position: absolute;
right: -40px;
bottom: -90px;
@keyframes pumpingIron {
0% { bottom: -90px; right: -40px; transform: rotate(20deg); }
100% { bottom: -20px; right: 70px; transform: rotate(-20deg); }

So a recap of the above CSS:

  1. Set the basic properties to #paul
  2. Absolutely position .arm and set the animation property with the relevant values. I’ve named the animation “pumping-iron”, set the animation-duration to 3s, used the boring-old linear timing-function and set the loop to infinite because Paul never gets tired of pumping-iron.
  3. Keyframe #1 sets the starting position of Paul’s arm and keyframe #2 sets the end position. The animation-direction value “alternate” tells the animation that once it has completed, it should alternate the keyframes. This brings the animation back to the starting position. The animation-iteration-count value “infinite” tells the animation to continue forever.

You would really feel the vendor-prefixes on this one. A prefix on the @keyframes means you duplicate that entire keyframe section 5 times! Looking at the prefixed version of animation and @keyframes is definitely intimidating, but as long as you realize it’s just CSS bloat you should be fine. Let’s take a look at this for visual reference… Be prepared:

[code type=”css”]
#paul .arm {
-webkit-animation: pumping-iron 2s ease-out alternate infinite;
-moz-animation: pumping-iron 2s ease-out alternate infinite;
-ms-animation: pumping-iron 2s ease-out alternate infinite;
-o-animation: pumping-iron 2s ease-out alternate infinite;
animation: pumping-iron 2s ease-out alternate infinite;
@-webkit-keyframes pumping-iron {
from { bottom: -90px; right: -40px; -webkit-transform: rotate(20deg); }
to { bottom: -20px; right: 70px; -webkit-transform: rotate(-20deg); }
@-moz-keyframes pumping-iron {
from { bottom: -90px; right: -40px; -moz-transform: rotate(20deg); }
to { bottom: -90px; right: -40px; -moz-transform: rotate(20deg); }
@-ms-keyframes pumping-iron {
from { bottom: -90px; right: -40px; -ms-transform: rotate(20deg); }
to { bottom: -90px; right: -40px; -ms-transform: rotate(20deg); }
@-o-keyframes pumping-iron {
from { bottom: -90px; right: -40px; -o-transform: rotate(20deg); }
to { bottom: -90px; right: -40px; -o-transform: rotate(20deg); }
@keyframes pumping-iron {
from { bottom: -90px; right: -40px; transform: rotate(20deg); }
to { bottom: -90px; right: -40px; transform: rotate(20deg); }

And now for the final product!

Cross Browser compatibility

To quote HTML5Please: “For now, either use animations only to provide non-essential aesthetic enhancements or use feature detection to provide an alternative experience for browsers that do not support this feature.”
Currently all modern browsers and/including IE10 support CSS animations with a vendor prefix. Next time you come across an animation you need to add, use CSS animations and either fall back to no animation or use Modernizr to detect for the support and fall back to the javascript you would have added anyway. Viva la progressive enhancement.

…And because Modernizr is so damn cool and simple to use I’ll briefly explain how exactly to make use of this feature detection and fallback option.

Modernizr adds various classes to the HTML element depending on whether the browser supports a feature or not. You could make use of classes such as .boxshadow, .no-boxshadow, .borderradius, .no-borderradius, etc. This puts the power of feature detection right into the CSS which is great and easy to make use of. You could also do more intricate feature detection by using their Modernizr javascript object.


I think you should all be using CSS animations right now, provided you include the vendor-prefixed versions and have a decent fallback for non-modern browsers.

1 Comment


  1. Animations in CSS - circlecube - [...] (with some thought to states), but animations bring in a whole extra dimension! Embedded Link CSS Animation: How it works…

Submit a Comment

Your email address will not be published. Required fields are marked *

More News & Articles