When I was in school to be a 3-D animator, I read a book called Timing for Animation. Though only 152 pages long, it’s essentially the bible for anyone looking to be a great animator. In fact, Pixar chief creative officer John Lasseter used the first edition as a reference when he was an animator at Walt Disney Studios in the early 1980s.
In the book, authors John Halas and Harold Whitaker advise:
Timing is the part of animation which gives meaning to movement. Movement can easily be achieved by drawing the same thing in two different positions and inserting a number of other drawings between the two. The result on the screen will be movement; but it will not be animation.
But that’s exactly what we’re doing with CSS3 and JavaScript: we’re moving elements, not animating them. We’re constantly specifying beginning and end states and allowing the technology to interpolate between the two. And yet, it’s the nuances within those middle frames that create the sense of life we’re looking for.
As bandwidth increases and browser rendering grows more consistent, we can create interactions in different ways than we’ve been able to before. We’re encountering motion more and more on sites we’d generally label ‘static.’ However, this motion is mostly just movement, not animation. It’s the manipulation of an element’s properties, most commonly width, height, x- and y-coordinates, and opacity.
So how do we create real animation?
The metaphor
In my experience, animation is most believable when it simulates, exaggerates, or defies the real world. A bowling ball falls differently than a racquetball. They each have different weights and sizes, which affect the way they land, bounce, and impact other objects.
This is a major reason that JavaScript animation frequently feels mechanical; it doesn’t complete a metaphor. Expanding and collapsing a <div> feels very different than a opening a door or unfolding a piece of paper, but it often shouldn’t. The interaction itself should tie directly to the art direction of a page.
Physics
Understanding the physics of a situation is key to creating convincing animation, even if your animation seeks to defy conventional physics. Isaac Newton’s first law of motion states, “Every body remains in a state of rest or uniform motion (constant velocity) unless it is acted upon by an external unbalanced force.” Once a force acts upon an object, the object’s shape can change accordingly, depending on the strength of the force and the mass of the object. Another nugget of wisdom from Halas and Whitaker:
All objects in nature have their own weight, construction, and degree of flexibility, and therefore each behaves in its own individual way when a force acts upon it. This behavior, a combination of position and timing, is the basis of animation. The basic question which an animator is continually asking himself is this: “What will happen to this object when a force acts upon it?” And the success of his animation largely depends on how well he answers this question.
In animating with CSS3 and JavaScript, keep physics in mind. How ‘heavy’ is the element you’re interacting with? What kind of force created the action? A gentle nudge? A forceful shove? These subtleties will add a sense of realism to your animations and make them much more believable to your users.
Misdirection
Magicians often use misdirection to get their audience to focus on one thing rather than another. They fool us into thinking something happened that actually didn’t.
Animation is the same, especially on a screen. By changing the arrangement of pixels on screen at a fast enough rate, your eyes fool your mind into thinking an object is actually in motion.
Another important component of misdirecting in animation is the use of multiple objects. Try to recall a cartoon where a character vanishes. More often, the character makes some sort of exaggerated motion (this is called anticipation) then disappears, and a puff a smoke follows. That smoke is an extra element, but it goes a long way into make you believe that character actually disappeared.
Very rarely does a vanishing character’s opacity simply go from one hundred per cent to zero. That’s not believable. So why do we do it with <div>s?
Armed with the ammunition of metaphors and misdirection, let’s code an example.
Shake, rattle, and roll
(These demos require at least a basic understanding of jQuery and CSS3. Run away if your’re afraid, or brush up on CSS animation and resources for learning jQuery. Also, these demos use WebKit-specific features and are best viewed in the latest version of Safari, so performance in other browsers may vary.)
We often see the design pattern of clicking a link to reveal content. Our first demo shows us exactly that. It uses jQuery’s slideDown() method, as many instances do.
But what force acted on the <div> that caused it to open? Did pressing the button unlatch some imaginary hook? Did it activate an unlocking sequence with some gears?
Take 2
Our second demo is more explicit about what happens: the button fell on the <div> and shook its content loose. Here’s how it’s done.
function clickHandler(){
$('#button').addClass('animate');
return false;
}
Clicking the link adds a class of animate to our button. That class has the following CSS associated with it:
<style>
.animate {
-webkit-animation-name: ANIMATE;
-webkit-animation-duration: 0.25s;
-webkit-animation-iteration-count: 1;
-webkit-animation-timing-function: ease-in;
}
@-webkit-keyframes ANIMATE {
from {
top: 72px;
}
to {
top: 112px;
}
}
In our keyframe definition, we’ve specified from and to states. This is great, because we can be explicit about how an object starts and finishes moving.
What’s also extra handy is that these CSS keyframes broadcast events that you can react to with JavaScript. In this example, we’re listening to the webkitAnimationEnd event and opening the <div> only when the sequence is complete. Here’s that code.
function attachAnimationEventHandlers(){
var wrap = document.getElementById('wrap');
wrap.addEventListener('webkitAnimationEnd', function($e) {
switch($e.animationName){
case "ANIMATE" :
openMain();
break;
default:
}
}, false);
}
function openMain(){
$(’#main .inner’).slideDown(‘slow’);
}
(For more info on handling animation events, check out the documentation at the Safari Reference Library.)
Take 3
The problem with the previous demo is that the subtleties of timing aren’t evident. It still feels a bit choppy.
For our third demo, we’ll use percentages instead of keywords so that we can insert as many points as we need to communicate more realistic timing. The percentages allow us to add the keys to well-timed animation: anticipation, hold, release, and reaction.
<style>
@-webkit-keyframes ANIMATE {
0% {
top: 72px;
}
40% { /* anticipation */
top: 57px;
}
70% { /* hold */
top: 56px;
}
80% { /* release */
top: 112px;
}
100% { /* return */
top: 72px;
}
}
</style>
Take 4
The button animation is starting to feel much better, but the reaction of the <div> opening seems a bit slow.
This fourth demo uses jQuery’s delay() method to time the opening precisely when we want it. Since we know the button’s animation is one second long and its reaction starts at eighty per cent of that, that puts our delay at 800ms (eighty per cent of one second). However, here’s a little pro tip: let’s start the opening at 750ms instead. The extra fifty milliseconds makes it feel more like the opening is a reaction to the exact hit of the button. Instead of listening for the webkitAnimationEnd event, we can start the opening as soon as the button is clicked, and the movement plays on the specified delay.
function clickHandler(){
$('#button').addClass('animate');
openMain();
return false;
}
function openMain(){
$(’#main .inner’).delay(750).slideDown(‘slow’);
}
Take 5
We can tweak the timing of that previous animation forever, but that’s probably as close as we’re going to get to realistic animation with CSS and JavaScript. However, for some extra sauce, we could relegate the whole animation in our final demo to a video sequence which includes more nuances and extra elements for misdirection.
Here’s the basis of video replacement. Add a <video> element to the page and adjust its opacity to zero. Once the button is clicked, fade the button out and start playing the video. Once the video is finished playing, fade it out and bring the button back.
function clickHandler(){
if($('#main .inner').is(':hidden')){
$('#button').fadeTo(100, 0);
$('#clickVideo').fadeTo(100, 1, function(){
var clickVideo = document.getElementById('clickVideo');
clickVideo.play();
setTimeout(removeVideo, 2400);
openMain();
});
}
return false;
}
function removeVideo(){
$(’#button’).fadeTo(500, 1);
$(’#clickVideo’).fadeOut(‘slow’);
}
function openMain(){
$(’#main .inner’).delay(1100).slideDown(‘slow’);
}
Wrapping up
I’m no JavaScript expert by any stretch. I’m sure a lot of you scripting wizards out there could write much cleaner and more efficient code, but I hope this gives you an idea of the theory behind more realistic motion with the technology we’re using most. This is just one model of creating more convincing animation, but you can create countless variations of this, including…
- Exporting
<video>animations in 3-D animation tools or 2-D animation tools like Flash or After Effects - Using
<canvas>or SVG instead of<video> - Employing specific JavaScript animation frameworks
- Making use of all the powerful properties of CSS Transforms and CSS Animation
- Trying out emerging CSS3 animation tools like Sencha Animator
If it wasn’t already apparent, these demos show an exaggerated example and probably aren’t practical in a lot of environments. However, there are a handful of great sites out there that honor animation techniques—metaphor, physics, and misdirection, among others—like Benjamin De Cock’s vCard, 20 Things I Learned About Browsers and the Web by Fantasy Interactive, and the Nike Snowboarding site by Ian Coyle and HEGA. They’re wonderful testaments to what you can do to aid interaction for users.
My goal was to show you the ‘why’ and the ‘how.’ Your charge is to discern the ‘where’ and the ‘when.’ Happy animating!


Comments
Comments are ordered by helpfulness, as indicated by you. Help us pick out the gems and discourage asshattery by voting on notable comments.
Got something to add? You can leave a comment below.
15/12/2010
Great article. There are a bunch of great tips that I’m definitely going to use in my next CSS3 animation. I’ve found that animating elements using different CSS positioning values results in choppy animation on mobile devices. The solution? The new CSS3 translate() property. I recently fixed a CSS3 animation by converting all the keyframes from positioning to translate(). Thanks again!
Vote Helpful or Unhelpful
15/12/2010
I’ve been saying this for years to my fellow designers, but thank you, Dan, for telling the world.
Animation doesn’t just have to be superfluous eye-candy; metaphor can help make computers seem more familiar and less intimidating to my grandmother.
Vote Helpful or Unhelpful
15/12/2010
Quick heads up, the video has a different color profile than the site graphics, making it possible to see the video:
http://cl.ly/3e3Q
Vote Helpful or Unhelpful
15/12/2010
Thanks for this introduction to CSS3 animation. I think that new tools will be released to support and create such animations, but when?
Vote Helpful or Unhelpful
15/12/2010
Tor – Thanks for the heads up. For this proof of concept, I’m not terribly worried about color issues. For production use, you’ll certainly want to make sure the transition from static graphic to video back to static graphic is as seamless as possible.
Nicolas – Your guess is as good as mine, although I’d wager that there are some things in production that will soon be released.
Vote Helpful or Unhelpful
15/12/2010
Awesome article! I’m definitely going to try something like this out.
Note: The anchor link which links to http://24ways.org/Scalable takes me to a 404 page.
Vote Helpful or Unhelpful
15/12/2010
NP, Dan.
Video content for interaction and other forms of non-primary content will hit the web big tiiime.
Vote Helpful or Unhelpful
15/12/2010
I haven’t read the whole article yet but I’ve looked through all the demo’s. Really smart. The video element is a cracking idea.
Needless to say, this has been bookmarked for future reference : )
Vote Helpful or Unhelpful
15/12/2010
By far the best article this year! Thanks for an article that exemplifies what I’ve come to expect from 24ways.
I’ve just begun to test animation with both jQuery and Mootools, and have noticed a very mechanical feel to it, but could never quite put my finger on why. This explains a lot, and I’ll definitely be picking up a book this week. ;-)
Thanks again, Dan!
Vote Helpful or Unhelpful
16/12/2010
Very good article Dan. This is a good awareness of what you can do with CSS3. This article made me invest more time in jquery and CSS3.
Lately I see more and more professional websites using this, so I guess it will be the future of webdesign.
Vote Helpful or Unhelpful
Impress us