I'm Dudley Storey, the author of Pro CSS3 Animation. This is my blog, where I talk about web design and development with HTML, CSS and SVG. To receive more information, including news, updates, and tips, you should follow me on Twitter or add me on Google+.

my books

Pro CSS3 Animation, Apress, 2013

Using SVG with CSS3 and HTML5, O'Reilly, 2017

my other blogs

Massive Head Canon: Intelligent discussion of movies, books, games, and technology.

my projects

The New Defaults — A Sass color keyword system for designers. Replaces CSS defaults with improved hues and more memorable, relevant color names.

CSSslidy — an auto-generated #RWD image slider. 3.8K of JS, no JQuery.

Introduction to CSS3 Animation

The basics of animating HTML elements with CSS3

Mouseover the image above to see an example of CSS3 animation. Photograph of Spartan C3 biplane provided by San Diego Air & Space Museum archive, licensed under Creative Commons.

CSS be used for more than the mere transformation of elements; it can also be used to animate them. You should be aware that CSS transitions are very much in draft. Safari / Chrome / Mobile Safari have the best support for CSS3 animation; the ability is also in Firefox 4+, Opera 10+, and IE9+.

This new ability in CSS definitely rubs up against JavaScript, which has traditionally been used for animation on web pages. However, animation still falls under the purview of CSS: remember, CSS is about the appearance of elements. That includes animation. The domain of JavaScript is behaviour, which is now defined at a deeper and (in some ways) more basic level. If you want to highlight alternating rows of a table, that’s CSS (the way something looks). If you want the data in the table to be sortable based on different criteria, that is JavaScript (the way something acts on a page).

The principles of CSS animation are very simple:

  1. Set up the default state of the element in CSS.
  2. Define how the element will appear in its final state.
  3. Write in a transition routine, written in CSS3, triggered by an event.
  4. In the routine, specify the period of time for the transition. You can also set what properties of the element should change during the animation, and the rate of change.

You can transition most every CSS property you can imagine, and some you likely cannot. Animating properties like opacity, to create fade in and fade out effects, or CSS3 transforms, like rotate, translate and scale, are obvious… but you can also animate color, background, shadow, width, height, z-index, columns, line-height and font-size, to name just a few.

Let’s say we have an image with an id of biplane on the page. We want to bring the page to life by having this image rotate slightly when the user places their mouse over it. If we were to do this without animation, but still in CSS3, the code would be very simple:

  1. img#biplane { width: 500px; height: 415px;
  2. border: 20px solid #ffe;
  3. -moz-box-shadow: 10px 10px 3px rgba(0, 0, 0, 0.3);
  4. -webkit-box-shadow: 10px 10px 3px rgba(0, 0, 0, 0.3);
  5. box-shadow: 10px 10px 3px rgba(0, 0, 0, 0.3); }
  6. /* sets up the basic visual properties for the image */
  7. img#biplane:hover {
  8. -moz-transform: rotate(7deg); -o-transform: rotate(7deg);
  9. -webkit-transform: rotate(7deg); transform: rotate(7deg); }

This works fine, except for the fact there is no transition between one state and the other: the image “jerks” when it rotates, as it moves in a single step. Let’s smooth this transition with more CSS3. At the very basic level, we need to specify only one property: how long it takes for the element to animate between its original state and the new orientation, a draft property called transition-duration:

  1. img#biplane:hover {
  2. -webkit-transition-duration: 1s;
  3. -moz-transition-duration: 1s;
  4. -o-transition-duration: 1s;
  5. transition-duration: 1s;
  6. moz-transform: rotate(7deg); -o-transform: rotate(7deg);
  7. -webkit-transform: rotate(7deg); transform: rotate(7deg); }

That’s it. Up-to-date browsers will transition the rotation of the image over 1 second; older browsers, such as Firefox 3.6, will still rotate the image, just without any transition between the two states.

Those closely observing the movement of the image will have noticed that the animation is automatically eased in and out: the rotation starts off slow, speeds up to reach a terminal velocity, and then slows down before it comes to rest (increasing the amount of rotation and/or the time taken to do so may enhance your perception of this).

Animation in CSS has easing: built-in organic, natural motion. If you want a more “mechanical” feel to the motion, you can achieve it by changing a property known as the transition timing function to linear:

  1. img#biplane:hover {
  2. -webkit-transition-duration: 1s;
  3. -moz-transition-duration: 1s;
  4. -o-transition-duration: 1s;
  5. -ms-transition-duration: 1s;
  6. transition-duration: 1s;
  7. -moz-transition-timing-function: linear;
  8. -o-transition-timing-function: linear;
  9. -webkit-transition-timing-function: linear;
  10. transition-timing-function: linear;
  11. -moz-transform: rotate(7deg);
  12. -o-transform: rotate(7deg);
  13. -ms-transform: rotate(7deg);
  14. -webkit-transform: rotate(7deg);
  15. transform: rotate(7deg);
  16. }

It’s possible to set the timing function to other values, or even to mathematically plot out Bezier function easing curves:

  1. transition-timing-function: ease | linear | ease-in|ease-out | ease-in-out |cubic-bezier(<number>, <number>, <number>, <number>)

Finally: if you’ve used the code above, you’ll see that the transition works on mouseover, but not when you move the mouse off the element: when that occurs, the image jerks back to its original position. To solve this problem, we do something that may appear counter-intuitive at first: we move the transition information out of the :hover state declaration and into the default state. At the same time, we should recognize that this code is getting a little long, even for CSS3: transition properties, like everything else, can be shortcut. Let’s move the code and re-write it at the same time:

  1. img#biplane { width: 500px; height: 415px;
  2. border: 20px solid #ffe;
  3. -moz-box-shadow: 10px 10px 3px rgba(0, 0, 0, 0.3);
  4. -webkit-box-shadow: 10px 10px 3px rgba(0, 0, 0, 0.3);
  5. box-shadow: 10px 10px 3px rgba(0, 0, 0, 0.3);
  6. -webkit-transition: all 1s ease-in-out;
  7. -ms-transition: all 1s ease-in-out;
  8. -moz-transition: all 1s ease-in-out;
  9. -o-transition: all 1s ease-in-out;
  10. transition: all 1s ease-in-out; }
  11. img#biplane:hover {
  12. -moz-transform: rotate(7deg); -o-transform: rotate(7deg);
  13. -webkit-transform: rotate(7deg); transform: rotate(7deg); }

Perhaps the easiest way to think of this is that we previously indicated that the transition only occurred on the way to the hover state; with this change, we are indicating that the transition affects all effects, over a 1 second period, using ease-in and ease-out, both to and from the default state.

This site helps millions of visitors while remaining ad-free. For less than the price of a cup of coffee, you can help pay for bandwidth and server costs while encouraging further articles.