⭐ If you would like to buy me a coffee, well thank you very much that is mega kind! : https://www.buymeacoffee.com/honeyvig Hire a web Developer and Designer to upgrade and boost your online presence with cutting edge Technologies
Showing posts with label Animations basics. Show all posts
Showing posts with label Animations basics. Show all posts

Wednesday, November 9, 2011

An Introduction To CSS3 Keyframe Animations

By now you’ve probably heard at least something about animation in CSS3 using keyframe-based syntax. The CSS3 animations module in the specification has been around for a couple of years now, and it has the potential to become a big part of Web design.
Using CSS3 keyframe animations, developers can create smooth, maintainable animations that perform relatively well and that don’t require reams of scripting. It’s just another way that CSS3 is helping to solve a real-world problem in an elegant manner. If you haven’t yet started learning the syntax for CSS3 animations, here’s your chance to prepare for when this part of the CSS3 spec moves past the working draft stage.
In this article, we’ll cover all the important parts of the syntax, and we’ll fill you in on browser support so that you’ll know when to start using it.
Animated Landscape Scene
[Editor's note: Have you already got your copy of the Smashing Book #2? The book shares valuable practical insight into design, usability and coding. Have a look at the contents.]

A Simple Animated Landscape Scene

For the purpose of this article, I’ve created a simple animated landscape scene to introduce the various aspects of the syntax. You can view the demo page to get an idea of what I’ll be describing. The page includes a sidebar that displays the CSS code used for the various elements (sun, moon, sky, ground and cloud). Have a quick look, and then follow along as I describe the different parts of the CSS3 animations module.
(NOTE: Safari has a bug that prevents the animation from finishing correctly. This bug seems to be fixed in Safari using a WebKit nightly build, so future versions of Safari should look the same as Chrome. See more under the heading “The Animation’s Fill Mode”)
I’ll describe the CSS related to only one of the elements: the animated sun. That should suffice to give you a good understanding of keyframe-based animations. For the other elements in the demo, you can examine the code on the demo page using the tabs.

The Keyframe @ Rule

The first unusual thing you’ll notice about any CSS3 animation code is the keyframes @ rule. According to the spec, this specialized CSS @ rule is followed by an identifier (chosen by the developer) that is referred to in another part of the CSS.
The @ rule and its identifier are then followed by a number of rule sets (i.e. style rules with declaration blocks, as in normal CSS code). This chunk of rule sets is delimited by curly braces, which nest the rule sets inside the @ rule, much as you would find with other @ rules.
Here’s the @ rule we’ll be using:
1@-webkit-keyframes sunrise {
2    /* rule sets go here … */
3}
The word sunrise is an identifier of our choosing that we’ll use to refer to this animation.
Notice that I’m using the -webkit- prefix for all of the code examples here and in the demo. I’ll discuss browser support at the end of this article, but for now it’s enough to know that the only stable browsers that support these types of animations are WebKit-based ones.

The Keyframe Selectors

Let’s add some rule sets inside the @ rule:
01@-webkit-keyframes sunrise {
02   0% {
03      bottom: 0;
04      left: 340px;
05      background: #f00;
06   }
07 
08   33% {
09      bottom: 340px;
10      left: 340px;
11      background: #ffd630;
12   }
13 
14   66% {
15      bottom: 340px;
16      left: 40px;
17      background: #ffd630;
18   }
19 
20   100% {
21      bottom: 0;
22      left: 40px;
23      background: #f00;
24   }
25}
With the addition of those new rule sets, we’ve introduced the keyframe selector. In the code example above, the keyframe selectors are 0%, 33%, 66%, and 100%. The 0% and 100% selectors could be replaced by the keywords “from” and “to,” respectively, and you would get the same results.
Each of the four rule sets in this example represents a different snapshot of the animated element, with the styles defining the element’s appearance at that point in the animation. The points that are not defined (for example, from 34% to 65%) comprise the transitional period between the defined styles.
Although the spec is still in development, some rules have been defined that user agents should follow. For example, the order of the keyframes doesn’t really matter. The keyframes will play in the order specified by the percentage values, and not necessarily the order in which they appear. Thus, if you place the “to” keyframe before the “from” keyframe, the animation would still play the same way. Also, if a “to” or “from” (or its percentage-based equivalent) is not declared, the browser will automatically construct it. So, the rule sets inside the @ rule are not governed by the cascade that you find in customary CSS rule sets.

The Keyframes That Animate the Sun

For the purpose of animating the sun in this demo, I’ve set four keyframes. As mentioned, the code above includes comments that describe the changes.
In the first keyframe, the sun is red (as if it were just rising or setting), and it is positioned below ground (i.e. not visible). Naturally, the element itself must be positioned relatively or absolutely in order for the left and bottom values to have any effect. I’ve also used z-index to stack the elements (to make sure, for example, that the ground is above the sun). Take note that the only styles shown in the keyframes are the styles that are animated. The other styles (such as z-index and position, which aren’t animated) are declared elsewhere in the style sheet and thus aren’t shown here.
10% {
2    bottom: 0; /* sun at bottom */
3    left: 340px; /* sun at right */
4    background: #f00; /* sun is red */
5}
About one third of the way into the animation (33%), the sun is on the same horizontal plane but has risen and changed to a yellow-orange (to represent full daylight):
133% {
2    bottom: 340px; /* sun rises */
3    left: 340px;
4    background: #ffd630; /* changes color */
5}
Then, at about two thirds into the animation (66%), the sun has moved to the left about 300 pixels but stays on the same vertical plane. Notice something else in the 66% keyframe: I’ve repeated the same color from the 33% keyframe, to keep the sun from changing back to red too early.
166% {
2    bottom: 340px;
3    left: 40px; /* sun moves left across sky */
4    background: #ffd630; /* maintains its color */
5}
Finally, the sun gradually animates to its final state (the full red) as it disappears below the ground.
1100% {
2    bottom: 0; /* sun sets */
3    left: 40px;
4    background: #f00; /* back to red */
5}

Associating The Animation Name With An Element

Here’s the next chunk of code we’ll add in our example. It associates the animation name (in this case, the word sunrise) with a specific element in our HTML:
1#sun.animate {
2    -webkit-animation-name: sunrise;
3}
Here we’re introducing the animation-name property. The value of this property must match an identifier in an existing @keyframes rule, otherwise no animation will occur. In some circumstances, you can use JavaScript to set its value to none (the only keyword that has been reserved for this property) to prevent an animation from occurring.
The object we’ve targeted is an element with an id of sun and a class of animate. The reason I’ve doubled up the id and class like this is so that I can use scripting to add the class name animate. In the demo, I’ve started the page statically; then, with the click of a button, all of the elements with a particular class name will have another class appended called animate. This will trigger all of the animations at the same time and will allow the animation to be controlled by the user.
Of course, that’s just one way to do it. As is the case with anything in CSS or JavaScript, there are other ways to accomplish the same thing.

The Animation’s Duration And Timing Function

Let’s add two more lines to our CSS:
1#sun.animate {
2    -webkit-animation-name: sunrise;
3    -webkit-animation-duration: 10s;
4    -webkit-animation-timing-function: ease;
5}
You can specify the duration of the animation using the animation-duration property. The duration represents the time taken to complete a single iteration of the animation. You can express this value in seconds (for example, 4s), milliseconds (2000ms), and seconds in decimal notation (3.3s).
The specification doesn’t seem to specify all of the available units of time measurement. However, it seems unlikely that anyone would need anything longer than seconds; and even then, you could express duration in minutes, hours or days simply by calculating those units into seconds or milliseconds.
The animation-timing-function property, when declared for the entire animation, allows you to define how an animation progresses over a single iteration of the animation. The values for animation-timing-function are ease, linear, ease-out, step-start and many more, as outlined in the spec.
For our example, I’ve chosen ease, which is the default. So in this case, we can leave out the property and the animation will look the same.
Additionally, you can apply a specific timing function to each keyframe, like this:
01@-webkit-keyframes sunrise {
02   0% {
03      background: #f00;
04      left: 340px;
05      bottom: 0;
06      -webkit-animation-timing-function: ease;
07   }
08 
09   33% {
10      bottom: 340px;
11      left: 340px;
12      background: #ffd630;
13      -webkit-animation-timing-function: linear;
14   }
15 
16   66% {
17      left: 40px;
18      bottom: 340px;
19      background: #ffd630;
20      -webkit-animation-timing-function: steps(4);
21   }
22 
23   100% {
24      bottom: 0;
25      left: 40px;
26      background: #f00;
27      -webkit-animation-timing-function: linear;
28   }
29}
A separate timing function defines each of the keyframes above. One of them is the steps value, which jerks the animation forward a predetermined number of steps. The final keyframe (100% or to) also has its own timing function, but because it is for the final state of a forward-playing animation, the timing function applies only if the animation is played in reverse.
In our example, we won’t define a specific timing function for each keyframe, but this should suffice to show that it is possible.

The Animation’s Iteration Count And Direction

Let’s now add two more lines to our CSS:
1#sun.animate {
2    -webkit-animation-name: sunrise;
3    -webkit-animation-duration: 10s;
4    -webkit-animation-timing-function: ease;
5    -webkit-animation-iteration-count: 1;
6    -webkit-animation-direction: normal;
7}
This introduces two more properties: one that tells the animation how many times to play, and one that tells the browser whether or not to alternate the sequence of the frames on multiple iterations.
The animation-iteration-count property is set to 1, meaning that the animation will play only once. This property accepts an integer value or infinite.
In addition, the animation-direction property is set to normal (the default), which means that the animation will play in the same direction (from start to finish) each time it runs. In our example, the animation is set to run only once, so the property is unnecessary. The other value we could specify here is alternate, which makes the animation play in reverse on every other iteration. Naturally, for the alternate value to take effect, the iteration count needs to have a value of 2 or higher.

The Animation’s Delay And Play State

Let’s add another two lines of code:
1#sun.animate {
2    -webkit-animation-name: sunrise;
3    -webkit-animation-duration: 10s;
4    -webkit-animation-timing-function: ease;
5    -webkit-animation-iteration-count: 1;
6    -webkit-animation-direction: normal;
7    -webkit-animation-delay: 5s;
8    -webkit-animation-play-state: running;
9}
First, we introduce the animation-delay property, which does exactly what you would think: it allows you to delay the animation by a set amount of time. Interestingly, this property can have a negative value, which moves the starting point partway through the animation according to negative value.
The animation-play-state property, which might be removed from the spec, accepts one of two possible values: running and paused. This value has limited practical use. The default is running, and the value paused simply makes the animation start off in a paused state, until it is manually played. You can’t specify a paused state in the CSS for an individual keyframe; the real benefit of this property becomes apparent when you use JavaScript to change it in response to user input or something else.

The Animation’s Fill Mode

We’ll add one more line to our code, the property to define the “fill mode”:
01#sun.animate {
02    -webkit-animation-name: sunrise;
03    -webkt-animation-duration: 10s;
04    -webkit-animation-timing-function: ease;
05    -webkit-animation-iteration-count: 1;
06    -webkit-animation-direction: normal;
07    -webkit-animation-delay: 5s;
08    -webkit-animation-play-state: running;
09    -webkit-animation-fill-mode: forwards;
10}
The animation-fill-mode property allows you to define the styles of the animated element before and/or after the animation executes. A value of backwards causes the styles in the first keyframe to be applied before the animation runs. A value of forwards causes the styles in the last keyframe to be applied after the animation runs. A value of both does both.
UPDATE: It seems that the animation-fill-mode property has been removed from the spec, or else was never there to begin with, so this property may not end up in the spec. Also, Chrome and Safari respond differently when it is used. Safari will only apply a value of “forwards” if there are exactly two keyframes defined. It always seems to use the 2nd keyframe as the “forwards” state, which is not how Chrome does it; Chrome uses the final keyframe, which seems to be correct behaviour. Additionally, I’ve confirmed that the most up to date WebKit nightly does not have this bug, so future versions of Safari will render this correctly.

Shorthand

Finally, the specification describes shorthand notation for animations, which combines six of the properties described above. This includes everything except animation-play-state and animation-fill-mode.

Some Notes On The Demo Page And Browser Support

As mentioned, the code in this article is for animating only a single element in the demo: the sun. To see the full code, visit the demo page. You can view all of the source together or use the tabs in the sidebar to view the code for individual elements in the animation.
The demo does not use any images, and the animation does not rely on JavaScript. The sun, moon and cloud are all created using CSS3’s border-radius, and the only scripting on the page is for the tabs on the right and for the button that lets users start and reset the animation.
If you view the page in anything but a WebKit browser, it won’t work. Firefox does not currently support keyframe-based animation, but support is expected for Firefox 5, and the -moz-based syntax for animations is supported in the latest Aurora build. So, to make the source code as future-proof as possible, I’ve included all of the -moz prefixes along with the standard syntax.
Here are the browsers that support CSS3 keyframe animations:
  • Chrome 2+,
  • Safari 4+,
  • Firefox 5+,
  • iOS Safari 3.2+,
  • Android 2.1+.
Although no official announcement has been made, support in Opera is expected. There’s no word yet on support in IE.

Further Reading

Tuesday, November 8, 2011

The Guide To CSS Animation: Principles and Examples

With CSS animation now supported in both Firefox and Webkit browsers, there is no better time to give it a try. Regardless of its technical form, whether traditional, computer-generated 3-D, Flash or CSS, animation always follows the same basic principles. In this article, we will take our first steps with CSS animation and consider the main guidelines for creating animation with CSS. We’ll be working through an example, building up the animation using the principles of traditional animation. Finally, we’ll see some real-world usages.



screenshot

CSS Animation Properties

Before diving into the details, let’s set up the basic CSS:
Animation is a new CSS property that allows for animation of most HTML elements (such as div, h1 and span) without JavaScript or Flash. At the moment, it’s supported in Webkit browsers, including Safari 4+, Safari for iOS (iOS 2+), Chrome 1+ and, more recently, Firefox 5. Unsupported browsers will simply ignore your animation code, so ensure that your page doesn’t rely on it!
Because the technology is still relatively new, prefixes for the browser vendors are required. So far, the syntax is exactly the same for each browser, with only a prefix change required. In the code examples below, we use the -webkit syntax.
All you need to get some CSS animation happening is to attach an animation to an element in the CSS:
01/* This is the animation code. */
02@-webkit-keyframes example {
03   from { transform: scale(2.0); }
04   to   { transform: scale(1.0); }
05}
06 
07/* This is the element that we apply the animation to. */
08div {
09   -webkit-animation-name: example;
10   -webkit-animation-duration: 1s;
11   -webkit-animation-timing-function: ease; /* ease is the default */
12   -webkit-animation-delay: 1s;             /* 0 is the default */
13   -webkit-animation-iteration-count: 2;    /* 1 is the default */
14   -webkit-animation-direction: alternate;  /* normal is the default */
15}
First, we have the animation code itself. This can appear anywhere in the CSS, as long as the element that you’re animating can find the relevant animation-name.
When assigning the animation to your element, you can also use the shorthand:
1div {
2-webkit-animation: example 1s ease 1s 2 alternate;
3}
We can cut this down further by not entering all of the values. Without a value specified, the browser will fall back to the default.
Those are the basics. We’ll work through more code in the following section.

Applying Principles of Traditional Animation

Disney — the masters of traditional animation, in my opinion — developed the 12 principles of traditional animation early on and documented them in its famous book The Illusion of Life. These basic principles can be applied to all manner of animation, and you needn’t be an expert in animation to follow along. We’ll be working through an example of CSS animation that uses the 12 principles, turning a basic animation into a more believable illusion.
These may just be bouncing balls, but you can see a world of difference between the two versions.
This example demonstrates the features of CSS animation. In the code below, we use empty divs to show how it works; this isn’t the most semantic way to code, as we all know, but the point is to show how simple it is to bring a page to life in a way that we haven’t been able to do before in the browser.

Squash and Stretch

screenshot
The crude bouncing ball is a great demonstration of this first point. If the ball falls at a high velocity and hits the floor, you’ll see it squash down from the force and then stretch back out as it bounces up.
At a basic level, this should give our animation a sense of weight and flexibility. If we dropped a bowling ball, we wouldn’t expect it to flex at all — it might just damage the floor.
We can apply this squash and stretch effect through a CSS3 property, transform:
1@-webkit-keyframes example {
2   0% { -webkit-transform: scaleY(1.0); }
3   50% { -webkit-transform: scaleY(1.2); }
4   100% { -webkit-transform: scaleY(1.0); }
5}
This will scale the object lengthwise (on the y axis, up and down) to 1.2 times the original size, and then revert to the original size.
We’re also using more complex timing for this animation. You can use from and to for basic animations. But you can also specify many actions for your animation using percentages, as shown here.
That covers the squashing. Now we need to move the object using translate. We can combine transforms together:
150% {
2-webkit-transform: translateY(-300px) scaleY(1.2);
3}
The translate property allows us to manipulate the object without changing any of its base properties (such as position, width or height), which makes it ideal for CSS animation. This particular translate property makes it look like the ball is bouncing off the floor at the mid-point of the animation.
(Please note: to view the sample animations, you’ll need the latest version of Firefox, Chrome or Safari. At the time of writing, Safari provides the best viewing experience of CSS animation.)
Yes, it still looks rubbish, but this small adjustment is the first step in making this animation more believable.

Anticipation

Anticipation adds suspense, or a sense of power, before the main action. For example, the bend in your legs before you jump helps viewers anticipate what will come next. In the case of our bouncing ball, simply adding a shadow beforehand suggests that something is falling from above.
We’ve added another div for the shadow, so that we can animate it separate from the ball.
To create anticipation here, we keep the ball from dropping into the scene immediately. We do this simply by adjusting the percentage timings so that there is no movement between the start point and the first action.
1@-webkit-keyframes example {
2   0% { -webkit-transform: translateY(-300px) scaleY(1.2); }
3   35% { -webkit-transform: translateY(-300px) scaleY(1.2); } /* Same position as 0% */
4   65% { -webkit-transform: translateY(0px) scaleY(1.2); }    /* Starts moving after 35% to this position */
5   67% { -webkit-transform: translateY(10px) scaleY(0.8); }
6   85% { -webkit-transform: translateY(-100px) scaleY(1.2); }
7   100% { -webkit-transform: translateY(0px); }
8}
At the 35% point of the animation, the ball is in the same location, positioned off the stage, not moving. Then, between 35% and 65%, it suddenly moves onto the stage, and the rest of the animation follows.
You can also use animation-delay to create anticipation:
1div {
2-webkit-animation-delay: 1s;
3}
However, this could have an undesired effect. The animation-delay property simply ignores any animation code until the specified time. So, if your animation starts in a position different from the element that you are animating, then the object will appear to suddenly jump as soon as the delayed animation starts.
This property works best for looping animations that begin and end in the same location.

Staging

screenshot
Try to give a stage to the scene; put the animation in context. Thinking back to Disney films, what would they be without the fantastic background artwork? That’s half of the magic!
The stage is also key to focusing attention. Much like on a theater stage, lighting will be cast on the most important area. The stage should add to the illusion. With our bouncing ball, I’ve added a simple background to focus on where the ball will land. Now the viewer knows that the action will take place in the center, and the scene is no longer lost in snow.

Straight-Ahead vs. Pose to Pose

In traditional animation, this is a choice in how to construct your animation. The straight-ahead option is to draw out every frame in the sequence. The pose-to-pose option is to create a few keyframes throughout the sequence, and then fill in the gaps later. Filling in these gaps is known as “in-betweening,” or “tweening,” a familiar term for those used to animating in Flash.
With CSS animation, we typically use the latter, pose to pose. That is, we’ll add keyframes of action, and then the browser will “tween” the intermediate frames automatically. However, we can learn from the straight-ahead technique, too. The browser can do only so many effects; sometimes, you have to do it the hard way and put in more animation hard-graft to get the desired effect.

Follow-Through and Overlapping

Also known as physics! Follow-through and overlapping are more commonly used in character animation for body movement, such as to show arms swaying as the character drops them or long hair falling. Think of someone with a big stomach turning quickly: their body will turn first, and their bulging gut will follow shortly after.
For us, this means getting the physics right when the ball drops. In the demonstrations above, the ball drops unnaturally, as if beyond the control of gravity. We want the ball to drop and then bounce. However, this is better achieved through the next principle.

Slow In and Out

This has to do with speeding up and slowing down. Imagine a car that is speeding along and has to come to a stop. If it were to stop instantly, it wouldn’t be believable. We know that cars take time to slow down, so we would have to animate the car braking and slowly coming to a stop.
This is also relevant to showing the effect of gravity. Imagine a child on a swing. As they approach the highest point, they will slow down. As they come back down and gain speed, their fastest point will be at the bottom of the arc. Then they will rise up on the opposite side, and the action repeats.
screenshot
Back to our example, by adjusting the in and out speeds, we can make the ball much more believable (finally).
When the ball hits the floor, the impact will make it bounce back up instantly. As it reaches its highest point, it will slow down. Now it looks like the ball is really dropping.
In CSS, we can control this with the animation-timing-function property:
1-webkit-animation-timing-function: ease-out;
This property takes the following values:
  • ease-inSlow at the beginning, and then speeds up.
  • ease-outFast at the beginning, and then slows to a stop.
  • ease-in-outStarts slow, speeds up in the middle, and then slows to a stop.
  • linearMoves at an even speed from start to finish.
You can also use the bezier-curve function to create your own easing speeds.

Arcs

screenshot
Similar to the follow-through principle of physics, arcs follow the basic principle of “what goes up must come down.” Arcs are useful in thinking about the trajectory of an object.
Let’s throw the ball in from the left of the stage. A convincing animation would predict the arc along which the ball will fall; and in our example it will have to predict the next arc along which the ball will fall when it bounces.
This animation can be a bit more fiddly to adjust in CSS. We want to animate the ball going up and down and side to side simultaneously. So, we want our ball to move in smoothly from the left, while continuing the bouncing animation that we’ve been working on. Rather than attempt to capture both actions as one animation, we’ll do two separate animations, which is easiest. For this demonstration, we’ll wrap our ball in another div and animate it separately.
The HTML:
1<div class="ball-arc">
2   <div class="ball">div>
3div>
And the CSS:
01.ball-arc {
02-webkit-animation: ball-x 2.5s cubic-bezier(0, 0, 0.35, 1);
03}
04   /* cubic-bezier here is to adjust the animation-timing speed.
05   This example makes the ball take longer to slow down. */
06 
07@-webkit-keyframes ball-x {
08   0% { -webkit-transform: translateX(-275px); }
09   100% { -webkit-transform: translateX(0px); }
10}
Here, we have one animation to move the ball sideways (ball-x) and another animation to bounce the ball (ball-y). The only downside to this method is that if you want something really complex, you could end up with a code soup with poor semantics!

Secondary Action

A secondary action is a subtlety that makes the animation much more real. It addresses the details. For example, if we had someone with long hair walking, the primary action would be the walking, and the secondary action would be the bounce of the hair, or perhaps the ruffling of the clothes in the wind.
In our example, it’s much simpler. By applying more detail to the ball, we make the secondary action the spinning of the ball. This will give the illusion that the ball is being thrown in.
Rather than add another div for this animation, we can be more specific by adding it to the new img element that we’re using to give the ball texture.
1.ball img {
2-webkit-animation: spin 2.5s;
3}
4 
5@-webkit-keyframes spin {
6   0% { -webkit-transform: rotate(-180deg); }
7   100% { -webkit-transform: rotate(360deg); }
8}

Timing

screenshot
This is simply the timing of your animation. The better the timing of the animation, the more realistic it will look.
Our ball is a perfect example of this. The current speed is about right for a ball this light. If it were a bowling ball, we would expect it to drop much more quickly. Whereas, if the animation were any slower, then it would look like we were playing tennis in space. The correct timing basically helps your animation look realistic.
You can easily adjust this with the animation-duration property, and you can adjust the individual timings of your animation using percentage values.

Exaggeration

Cartoons are known for exaggeration, or impossible physics. A cartoon character can contort into any shape and still manage to spring back to normal. In most cases, though, exaggeration is used for emphasis, to bring to life an action that would otherwise look flat in animation.
Nevertheless, use exaggeration modestly. Disney had a rule to base its animations on reality but push it slightly further. Imagine a character running into a wall; its body would squash into the wall more than expected, to emphasize the force of impact.
We’re using exaggeration in combination with squash and stretch to make it really obvious when the ball hits the floor. I’ve also added a subtle wobble to the animation. Finally, we also stretch the ball in and out as it bounces up and down to emphasize the speed.
Just as when we added one animation onto another, here we’ll add another div, which will wobble in sync with the ball hitting the floor:
01@-webkit-keyframes wobble {
02 
030%, 24%, 54%, 74%, 86%, 96%, 100% {
04   -webkit-transform: scaleX(1.0);
05/* Make the ball a normal size at these points */
06}
07 
0825%, 55%, 75% {
09   -webkit-transform: scaleX(1.3) scaleY(0.8) translateY(10px);
10/* Points hitting the floor: squash effect */
11}
12 
1330%, 60%, 80% {
14   -webkit-transform: scaleX(0.8) scaleY(1.2);
15/* Wobble inwards after hitting the floor */
16}
17 
1875%, 87% {
19   -webkit-transform: scaleX(1.2);
20/* Subtler squash for the last few bounces */
21}
22 
2397% -webkit-transform: scaleX(1.1);
24/* Even subtler squash for last bounce */
25}
26 
27}
The code looks more complex than it is. It’s simple trial and error. Keep trying until you get the right effect!

Solid Drawing and Appeal

I have nothing more to teach you… at least not in code. These final two animation principles cannot be shown in code. They are skills you will have to perfect in order to make truly amazing animations.
When Disney started production on Snow White, it had its animators go back to life drawing classes and learn the human form again. This attention to detail is evident in the film, which goes to show that good animation requires solid drawing skills and sound knowledge of the form you are animating.
Most CSS animation will likely not be as complex as intricate figure animations, but the basic principle holds true. Whether a door is opening to reveal content or a “contact us” envelope is being sealed and delivered, the animation should be believable, not robotic… unless you’re animating a machine.
The appeal, or charisma, of each character will be unique. But as Disney has always shown, anything can have character: a teapot, a tree, even spoons. But with CSS, consider how the overall animation will contribute to the design and make the overall experience more satisfying. We don’t want to make clippy animations here.

Go Forth And Animate!

CSS animation is a great new feature. As with every new CSS feature, it will be overused and misused at first. There is even the slight danger that we’ll see a return of those long-winded Flash-style animated splash pages. Although I have faith in the Web community not to do this.
CSS animation can be used to really bring a website to life. While the code for our bouncing ball may not be the most semantic, it hopefully shows how simple it can be to bring almost anything on the page to life with CSS.
It can bring much-needed interaction to your elements (sans Flash!); it can add excitement to the page; and in combination with JavaScript, it can even be an alternative way to animate for games. By taking in the 12 principles above and working away at your animation, you can make your websites more convincing, enticing and exciting, leading to a better experience overall.

CSS Animation Tools

While knowing the CSS itself is great, plenty of tools are popping up that will help you animate. The 12 principles apply regardless, but if you’re worried about the code, these great tools let you try out CSS animation without getting too technical.

CSS Animation in the Wild

Finally, to get you excited about what is possible, here are some great examples of CSS animation being used on live websites:

Create An Animated Bar Graph With HTML, CSS And jQuery

People in boardrooms across the world love a good graph. They go nuts for PowerPoint, bullet points and phrases like “run it up the flagpole,” “blue-sky thinking” and “low-hanging fruit,” and everything is always “moving forward.” Backwards is not an option for people who facilitate paradigm shifts in the zeitgeist. Graphs of financial projections, quarterly sales figures and market saturation are a middle-manager’s dream.
screenshot
How can we as Web designers get in on all of this hot graph action? There are actually quite a few ways to display graphs on the Web. We could simply create an image and nail it to a Web page. But that’s not very accessible or interesting. We could use Flash, which is quite good for displaying graphs — but again, not very accessible. Besides, designers, developers and deities are falling out of love with Flash. Technologies such as HTML5 can do many of the same things without the need for a plug-in. The new HTML5 element could even be adapted to the task. Plenty of charting tools are online that we might use. But what if we wanted something a little more tailored?
There are pros and cons to the wide range of resources available to us, but this tutorial will not explore them all. Instead, we’ll create our graph using a progressively enhanced sprinkling of CSS3 and jQuery. Because we can.

What Are We Making?

We’re making this. And more! Here are some possibilities on how you can extend the techniques explored in this tutorial:
  • A progress bar that indicates how long until the end of all humanity in the event of a zombie plague;
  • A graph indicating the decline in safe outdoor activities during a zombie plague;
  • A frighteningly similar graph indicating the decline in manners during a zombie plague;
  • The increase of people who were unaware of the zombie plague because they were sharing with all of their now-deceased friends on Facebook what they did on FarmVille.
Or you could create a graph or quota bar that simply illustrates something useful and less full of dread and zombies. So, let’s get on with it.

What You’ll Need

  • A text or HTML editor. Take your pick; many are out there.
  • jQuery. Practice safe scripting and get the latest one. Keep the jQuery website open so that you can look up the documentation as you go.
  • Possibly an image editor, such as Paint, to mock up what your graph might look like.
  • A modern and decent Web browser to preview changes.
That should do it. Please note that this tutorial is not designed as an introduction to either HTML, CSS, jQuery or zombies. Some intermediate knowledge of these three technologies and the undead is assumed.

The Mark-Up

You can create the underlying HTML for a graph in a number of ways. In this tutorial, we’ll start with a table, because it will make the most sense visually if JavaScript or CSS is not applied. That’s a big checkmark in the column for accessibility.
Quick! You’ve just been given some alarming figures. The population of tanned zombies is projected to spiral out of control in the next few years. The carbon tigers and blue monkeys are under immediate threat. Then the tanned zombies will probably come for us. But you’re just a designer. What could you possibly do to help?
I know! You could make a Web page that illustrates our imminent demise with nice, calming, smoothly animated graphics!
To begin, let’s put this data into a table, with columns for each year, and rows for the different species.
01
02<html lang="en">
03   <head>
04      <meta charset="utf-8">
05      <meta name="viewport" content="width=1024">
06      <title>Example 01: No CSStitle>
07   head>
08
09   <body>
10      <div id="wrapper">
11         <div class="chart">
12            <h3>Population of endangered species from 2012 to 2016h3>
13            <table id="data-table" border="1" cellpadding="10" cellspacing="0"
14            summary="The effects of the zombie outbreak on the populations
15            of endangered species from 2012 to 2016">
16               <caption>Population in thousandscaption>
17               <thead>
18                  <tr>
19                     <tdtd>
20                     <th scope="col">2012th>
21                     <th scope="col">2013th>
22                     <th scope="col">2014th>
23                     <th scope="col">2015th>
24                     <th scope="col">2016th>
25                  tr>
26               thead>
27               <tbody>
28                  <tr>
29                     <th scope="row">Carbon Tigerth>
30                     <td>4080td>
31                     <td>6080td>
32                     <td>6240td>
33                     <td>3520td>
34                     <td>2240td>
35                  tr>
36                  <tr>
37                     <th scope="row">Blue Monkeyth>
38                     <td>5680td>
39                     <td>6880td>
40                     <td>6240td>
41                     <td>5120td>
42                     <td>2640td>
43                  tr>
44                  <tr>
45                     <th scope="row">Tanned Zombieth>
46                     <td>1040td>
47                     <td>1760td>
48                     <td>2880td>
49                     <td>4720td>
50                     <td>7520td>
51                  tr>
52               tbody>
53            table>
54         div>
55      div>
56   body>
57html>
View the example below to see how it looks naked, with no CSS or JavaScript applied. The accessibility of this table will enable people using screen readers to understand the data and the underlying message, which is “Run for your life! The zombies are coming!”
screenshot
The easy part is now out of the way. Now, let’s tap into the power of CSS and JavasScript (via jQuery) to really illustrate what the numbers are telling us. Technically, our aim is to create a graph that works in all modern browsers, from IE 8 on.
Did I say all modern browsers? IE 8 is lucky: it gets to hang out with the cool kids. Browsers that support CSS3 will get a few extra sprinkles.

“By Your Powers Combined…”

If you wish to summon Captain Planet, you may have to look elsewhere. If you want to learn how to combine CSS and jQuery to create a graph that illustrates our impending doom at the hands of a growing army of zombies who prefer bronzer over brains, then read on.
The first thing to do is style our table with some basic CSS. This is a nice safety net for people who haven’t enabled JavaScript in their browser.
screenshot

Getting Started In jQuery

We’ll use jQuery to create our graph on the fly, separate from the original data table. To do this, we need to get the data out of the table and store it in a more usable format. Then, we can add to our document new elements that use this data in order to construct our graph.
Let’s get started by creating our main createGraph() function. I’ve abbreviated some of the inner workings of this function so that you get a clearer picture of the structure. Don’t forget: you can always refer to the source code that comes with this tutorial.
Here’s our basic structure:
01// Wait for the DOM to load everything, just to be safe
02$(document).ready(function() {
03
04   // Create our graph from the data table and specify a container to put the graph in
05   createGraph('#data-table', '.chart');
06
07   // Here be graphs
08   function createGraph(data, container) {
09      // Declare some common variables and container elements
10      
11
12      // Create the table data object
13      var tableData = {
14         
15      }
16
17      // Useful variables to access table data
18      
19
20      // Construct the graph
21      
22
23      // Set the individual heights of bars
24      function displayGraph(bars) {
25         
26      }
27
28      // Reset the graph's settings and prepare for display
29      function resetGraph() {
30         
31         displayGraph(bars);
32      }
33
34      // Helper functions
35      
36
37      // Finally, display the graph via reset function
38      resetGraph();
39   }
40});
We pass two parameters to this function:
  1. The data, in the form of a table element;
  2. A container element, where we’d like to place our graph in the document.
Next up, we’ll declare some variables to manage our data and container elements, plus some timer variables for animation. Here’s the code:
01// Declare some common variables and container elements
02var bars = [];
03var figureContainer = $('
');
04var graphContainer = $('
');
05var barContainer = $('
');
06var data = $(data);
07var container = $(container);
08var chartData;
09var chartYMax;
10var columnGroups;
11
12// Timer variables
13var barTimer;
14var graphTimer;
Nothing too exciting here, but these will be very useful later.

Getting The Data

Besides simply displaying the data, a good bar chart should have a nice big title, clearly labelled axes and a color-coded legend. We’ll need to strip the data out of the table and format it in a way that is more meaningful in a graph. To do that, we’ll create a JavaScript object that stores our data in handy little functions. Let’s give birth to our tableData{} object:
01// Create table data object
02var tableData = {
03   // Get numerical data from table cells
04   chartData: function() {
05      
06   },
07   // Get heading data from table caption
08   chartHeading: function() {
09      
10   },
11   // Get legend data from table body
12   chartLegend: function() {
13      
14   },
15   // Get highest value for y-axis scale
16   chartYMax: function() {
17      
18   },
19   // Get y-axis data from table cells
20   yLegend: function() {
21      
22   },
23   // Get x-axis data from table header
24   xLegend: function() {
25      
26   },
27   // Sort data into groups based on number of columns
28   columnGroups: function() {
29      
30   }
31}
We have several functions here, and they are explained in the code’s comments. Most of them are quite similar, so we don’t need to go through each one. Instead, let’s pick apart one of them, columnGroups:
01// Sort data into groups based on number of columns
02columnGroups: function() {
03   var columnGroups = [];
04   // Get number of columns from first row of table body
05   var columns = data.find('tbody tr:eq(0) td').length;
06   for (var i = 0; i < columns; i++) {
07      columnGroups[i] = [];
08      data.find('tbody tr').each(function() {
09         columnGroups[i].push($(this).find('td').eq(i).text());
10      });
11   }
12   return columnGroups;
13}
Here’s how it breaks down:
  • Create the columnGroups[] array to store the data;
  • Get the number of columns by counting the table cells (td) in the first row;
  • For each column, find the number of rows in the table body (tbody), and create another array to store the table cell data;
  • Then loop through each row and grab the data from each table cell (via the jQuery text() function), and then add it to the table cell data array.
Once our object is full of juicy data, we can start creating the elements that make up our graph.

Using The Data

Using the jQuery $.each function, we can now loop through our data at any point and create the elements that make up our graph. One of the trickier bits involves inserting the bars that represent each species inside the yearly columns.
Here’s the code:
01// Loop through column groups, adding bars as we go
02$.each(columnGroups, function(i) {
03   // Create bar group container
04   var barGroup = $('
');
05   // Add bars inside each column
06   for (var j = 0, k = columnGroups[i].length; j < k; j++) {
07      // Create bar object to store properties (label, height, code, etc.) and add it to array
08      // Set the height later in displayGraph() to allow for left-to-right sequential display
09      var barObj = {};
10      barObj.label = this[j];
11      barObj.height = Math.floor(barObj.label / chartYMax * 100) + '%';
12      barObj.bar = $('
+ j + '">' + barObj.label + '
')
13         .appendTo(barGroup);
14      bars.push(barObj);
15   }
16   // Add bar groups to graph
17   barGroup.appendTo(barContainer);
18});
Excluding the headings, our table has five columns with three rows. For our graph, this means that for each column we create, three bars will appear in that column. The following image shows how our graph will be constructed:
screenshot
Breaking it down:
  • For each column, create a container div;
  • Loop inside each column to get the row and cell data;
  • Create a bar object (barObj{}) to store the properties for each bar, such as its label, height and mark-up;
  • Add the mark-up property to the column, applying a CSS class of '.fig' + j to color code each bar in the column, wrapping the label in a span;
  • Add the object to our bars[] array so that we can access the data later;
  • Piece it all together by adding the columns to a container element.
Bonus points if you noticed that we didn’t set the height of the bars. This is so that we have more control later on over how the bars are displayed.
Now that we have our bars, let’s work on labelling our graph. Because the code to display the labels is quite similar, talking you through all of it won’t be necessary. Here’s how we display the y-axis:
1// Add y-axis to graph
2var yLegend   = tableData.yLegend();
3var yAxisList   = $('
    ');
    4$.each(yLegend, function(i) {
    5   var listItem = $('

  • ' + this + '




  • ')
    6      .appendTo(yAxisList);
    7});
    8yAxisList.appendTo(graphContainer);
    This breaks down as follows:
    • Get the relevant table data for our labels,
    • Create an unordered list (ul) to contain our list items;
    • Loop through the label data, and create a list item (li) for each label, wrapping each label in a span;
    • Attach the list item to our list;
    • Finally, attach the list to a container element.
    By repeating this technique, we can add the legend, x-axis labels and headings for our graph.
    Before we can display our graph, we need to make sure that everything we’ve done is added to our container element.
    1// Add bars to graph
    2barContainer.appendTo(graphContainer);     
    3
    4// Add graph to graph container
    5graphContainer.appendTo(figureContainer);
    6
    7// Add graph container to main container
    8figureContainer.appendTo(container);

    Displaying The Data

    All that’s left to do in jQuery is set the height of each bar. This is where our earlier work, storing the height property in a bar object, will come in handy.
    We’re going to animate our graph sequentially, one by one, uno por uno.
    One possible solution is to use a callback function to animate the next bar when the last animation is complete. However, the graph would take too long to animate. Instead, our graph will use a timer function to display each bar after a certain amount of time, regardless of how long each bar takes to grow. Rad!
    Here’s the displayGraph() function:
    01// Set the individual height of bars
    02function displayGraph(bars, i) {
    03   // Changed the way we loop because of issues with $.each not resetting properly
    04   if (i < bars.length) {
    05      // Animate the height using the jQuery animate() function
    06      $(bars[i].bar).animate({
    07         height: bars[i].height
    08      }, 800);
    09      // Wait the specified time, then run the displayGraph() function again for the next bar
    10      barTimer = setTimeout(function() {
    11         i++;
    12         displayGraph(bars, i);
    13      }, 100);
    14   }
    15}
    What’s that you say? “Why aren’t you using the $.each function like you have everywhere else?” Good question. First, let’s discuss what the displayGraph() function does, then why it is the way it is.
    The displayGraph() function accepts two parameters:
    1. The bars to loop through,
    2. An index (i) from which to start iterating (starting at 0).
    Let’s break down the rest:
    • If the value of i is less than the number of bars, then keep going;
    • Get the current bar from the array using the value of i;
    • Animate the height property (calculated as a percentage and stored in bars[i].height);
    • Wait 100 milliseconds;
    • Increment i by 1 and repeat the process for the next bar.
    “So, why wouldn’t you just use the $.each function with a delay() before the animation?”
    You could, and it would work just fine… the first time. But if you tried to reset the animation via the “Reset graph” button, then the timing events wouldn’t clear properly and the bars would animate out of sequence.
    I would like to be proven wrong, and if there is a better way to do this, feel free to sound off in the comments section.
    Moving on, here’s resetGraph():
    01// Reset graph settings and prepare for display
    02function resetGraph() {
    03   // Stop all animations and set the bar's height to 0
    04   $.each(bars, function(i) {
    05      $(bars[i].bar).stop().css('height', 0);
    06   });
    07
    08   // Clear timers
    09   clearTimeout(barTimer);
    10   clearTimeout(graphTimer);
    11
    12   // Restart timer
    13   graphTimer = setTimeout(function() {
    14      displayGraph(bars, 0);
    15   }, 200);
    16}
    Let’s break resetGraph() down:
    • Stop all animations, and set the height of each bar back to 0;
    • Clear out the timers so that there are no stray animations;
    • Wait 200 milliseconds;
    • Call displayGraph() to animate the first bar (at index 0).
    Finally, call resetGraph() at the bottom of createGraph(), and watch the magic happen as we bask in the glory of our hard work.
    Not so fast, sunshine! Before we go any further, we need to put some clothes on.

    The CSS

    The first thing we need to do is hide the original data table. We could do this in a number of ways, but because our CSS will load well before the JavaScript, let’s do this in the easiest way possible:
    1#data-table {
    2   display: none;
    3}
    Done. Let’s create a nice container area to put our graph in. Because a few unordered lists are being used to make our graph, we’ll also reset the styles for those. Giving the #figure and .graph elements a position: relative is important because it will anchor the place elements exactly where we want in those containers.
    01/* Containers */
    02
    03#wrapper {
    04   height: 420px;
    05   left: 50%;
    06   margin: -210px 0 0 -270px;
    07   position: absolute;
    08   top: 50%;
    09   width: 540px;
    10}
    11
    12#figure {
    13   height: 380px;
    14   position: relative;
    15}
    16
    17#figure ul {
    18   list-style: none;
    19   margin: 0;
    20   padding: 0;
    21}
    22
    23.graph {
    24   height: 283px;
    25   position: relative;
    26}
    Now for the legend. We position the legend right down to the bottom of its container (#figure) and line up the items horizontally:
    01/* Legend */
    02
    03.legend {
    04   background: #f0f0f0;
    05   border-radius: 4px;
    06   bottom: 0;
    07   position: absolute;
    08   text-align: left;
    09   width: 100%;
    10}
    11
    12.legend li {
    13   display: block;
    14   float: left;
    15   height: 20px;
    16   margin: 0;
    17   padding: 10px 30px;
    18   width: 120px;
    19}
    20
    21.legend span.icon {
    22   background-position: 50% 0;
    23   border-radius: 2px;
    24   display: block;
    25   float: left;
    26   height: 16px;
    27   margin: 2px 10px 0 0;
    28   width: 16px;
    29}
    The x-axis is very similar to the legend. We line up the elements horizontally and anchor them to the bottom of its container (.graph):
    01/* x-axis */
    02
    03.x-axis {
    04   bottom: 0;
    05   color: #555;
    06   position: absolute;
    07   text-align: center;
    08   width: 100%;
    09}
    10
    11.x-axis li {
    12   float: left;
    13   margin: 0 15px;
    14   padding: 5px 0;
    15   width: 76px;
    16}
    The y-axis is a little more involved and requires a couple of tricks. We give it a position: absolute to break it out of the normal flow of content, but anchored to its container. We stretch out each li to the full width of the graph and add a border across the top. This will give us some nice horizontal lines in the background.
    Using the power of negative margins, we can offset the numerical labels inside the span so that they shift up and to the left. Lovely!
    01/* y-axis */
    02
    03.y-axis {
    04   color: #555;
    05   position: absolute;
    06   text-align: right;
    07   width: 100%;
    08}
    09
    10.y-axis li {
    11   border-top: 1px solid #ccc;
    12   display: block;
    13   height: 62px;
    14   width: 100%;
    15}
    16
    17.y-axis li span {
    18   display: block;
    19   margin: -10px 0 0 -60px;
    20   padding: 0 10px;
    21   width: 40px;
    22}
    Now for the meat in our endangered species sandwich: the bars themselves. Let’s start with the container element for the bars and the columns:
    01/* Graph bars */
    02
    03.bars {
    04   height: 253px;
    05   position: absolute;
    06   width: 100%;
    07   z-index: 10;
    08}
    09
    10.bar-group {
    11   float: left;
    12   height: 100%;
    13   margin: 0 15px;
    14   position: relative;
    15   width: 76px;
    16}
    Nothing too complicated here. We’re simply setting some dimensions for the container, and setting a z-index to make sure it appears in front of the y-axis markings.
    Now for each individual .bar:
    01.bar {
    02   border-radius: 3px 3px 0 0;
    03   bottom: 0;
    04   cursor: pointer;
    05   height: 0;
    06   position: absolute;
    07   text-align: center;
    08   width: 24px;
    09}
    10
    11.bar.fig0 {
    12   left: 0;
    13}
    14
    15.bar.fig1 {
    16   left: 26px;
    17}
    18
    19.bar.fig2 {
    20   left: 52px;
    21}
    The main styles to note here are:
    • position: absolute and bottom: 0, which means that the bars will be attached to the bottom of our graph and grow up;
    • the bar for each species (.fig0, .fig1 and .fig2), which will be positioned within .bar-group.
    Now, why don’t we minimize the number of sharp edges on any given page by using the border-radius property to round the edges of the top-left and top-right corners of each bar? OK, so border-radius isn’t really necessary, but it adds a nice touch for browsers that support it. Thankfully, the latest versions of the most popular browsers do support it.
    Because we’ve placed the values from each table cell in each bar, we can add a neat little pop-up that appears when you hover over a bar:
    01.bar span {
    02   #fefefe url(../images/info-bg.gif) 0 100% repeat-x;
    03   border-radius: 3px;
    04   left: -8px;
    05   display: none;
    06   margin: 0;
    07   position: relative;
    08   text-shadow: rgba(255, 255, 255, 0.8) 0 1px 0;
    09   width: 40px;
    10   z-index: 20;
    11
    12   -webkit-box-shadow: rgba(0, 0, 0, 0.6) 0 1px 4px;
    13   box-shadow: rgba(0, 0, 0, 0.6) 0 1px 4px;
    14}
    15
    16.bar:hover span {
    17   display: block;
    18   margin-top: -25px;
    19}
    First, the pop-up is hidden from view via display: none. Then, when a .bar element is hovered over, we’ve set display: block to bring it into view, and set a negative margin-top to make it appear above each bar.
    The text-shadow, rgba and box-shadow properties are currently supported by most modern browsers as is. Of these modern browsers, only Safari requires a vendor prefix (-webkit-) to make box-shadow work. Note that these properties are simply enhancements to our graph and aren’t required to understand it. Our baseline of Internet Explorer 8 simply ignores them.
    Our final step in bringing everything together is to color code each bar:
    01.fig0 {
    02   background: #747474 url(../images/bar-01-bg.gif) 0 0 repeat-y;
    03}
    04
    05.fig1 {
    06   background: #65c2e8 url(../images/bar-02-bg.gif) 0 0 repeat-y;
    07}
    08
    09.fig2 {
    10   background: #eea151 url(../images/bar-03-bg.gif) 0 0 repeat-y;
    11}
    In this example, I’ve simply added a background-color and a background-image that tiles vertically. This will update the styles for the bars and the little icons that represent them in the legend. Nice.
    And, believe it or not, that is it!

    The Finished Product

    screenshot
    That about wraps it up. I hope we’ve done enough to alert the public to the dangers of zombie over-population. More than that, however, I hope you’ve gained something useful from this tutorial and that you’ll continue to push the boundaries of what can be done in the browser — especially with proper Web standards and without the use of third-party plug-ins. If you’ve got ideas on how to extend or improve anything you’ve seen here, don’t hesitate to leave a comment below.

    Bonus: Unleashing The Power Of CSS3

    This bonus is not as detailed as our main example. It serves mainly as a showcase of some features being considered in the CSS3 specification.
    Because support for CSS3 properties is currently limited, so is their use. Although some of the features mentioned here are making their way into other Web browsers, Webkit-based ones such as Apple Safari and Google Chrome are leading the way.
    We can actually create our graph using no images at all, and even animate the bars using CSS instead of jQuery.
    Let’s start by removing the background images from our bars, replacing them with the -webkit-gradient property:
    01.fig0 {
    02   background: -webkit-gradient(linear, left top, right top, color-stop(0.0, #747474), color-stop(0.49, #676767), color-stop(0.5, #505050), color-stop(1.0, #414141));
    03}
    04
    05.fig1 {
    06   background: -webkit-gradient(linear, left top, right top, color-stop(0.0, #65c2e8), color-stop(0.49, #55b3e1), color-stop(0.5, #3ba6dc), color-stop(1.0, #2794d4));
    07}
    08
    09.fig2 {
    10   background: -webkit-gradient(linear, left top, right top, color-stop(0.0, #eea151), color-stop(0.49, #ea8f44), color-stop(0.5, #e67e28), color-stop(1.0, #e06818));
    11}
    We can do the same with our little number pop-ups:
    1.bar span {
    2   background: -webkit-gradient(linear, left top, left bottom, color-stop(0.0, #fff), color-stop(1.0, #e5e5e5));
    3   
    4}
    For more information on Webkit gradients, check out the Surfin’ Safari blog.
    Continuing with the pop-ups, let’s introduce -webkit-transition. CSS transitions are remarkably easy to use and understand. When the browser detects a change in an element’s property (height, width, color, opacity, etc.), it will transition to the new property.
    Again, refer to Surfin’ Safari for more information on -webkit-transition and CSS3 animation.
    Here’s an example:
    01.bar span {
    02   background: -webkit-gradient(linear, left top, left bottom, color-stop(0.0, #fff), color-stop(1.0, #e5e5e5));
    03   display: block;
    04   opacity: 0;
    05
    06   -webkit-transition: all 0.2s ease-out;
    07}
    08
    09.bar:hover span {
    10   opacity: 1;
    11}
    When you hover over the bar, the margin and opacity of the pop-up will change. This triggers a transition event according to the properties we have set. Very cool.
    Thanks to -webkit-transition, we can simplify our JavaScript functions a bit:
    01// Set individual height of bars
    02function displayGraph(bars, i) {
    03   // Changed the way we loop because of issues with $.each not resetting properly
    04   if (i < bars.length) {
    05      // Add transition properties and set height via CSS
    06      $(bars[i].bar).css({'height': bars[i].height, '-webkit-transition': 'all 0.8s ease-out'});
    07      // Wait the specified time, then run the displayGraph() function again for the next bar
    08      barTimer = setTimeout(function() {
    09         i++;
    10         displayGraph(bars, i);
    11      }, 100);
    12   }
    13}
    14// Reset graph settings and prepare for display
    15function resetGraph() {
    16   // Set bar height to 0 and clear all transitions
    17   $.each(bars, function(i) {
    18      $(bars[i].bar).stop().css({'height': 0, '-webkit-transition': 'none'});
    19   });
    20
    21   // Clear timers
    22   clearTimeout(barTimer);
    23   clearTimeout(graphTimer);
    24
    25   // Restart timer
    26   graphTimer = setTimeout(function() {
    27      displayGraph(bars, 0);
    28   }, 200);
    29}
    Here are the main things we’ve changed:
    • Set the height of the bars via the jQuery css() function, and allowed CSS transitions to take care of the animation;
    • When resetting the graph, turned transitions off so that the height of the bars is instantly set to 0.
    Check out the example if you have the latest version of Safari or Chrome installed.

    Ultra-Mega Webkit Bonus: Now In 3-D!

    For a sneak peek of what the future holds, check out a little experiment that I put together, with a 3-D effect and CSS transforms. Again, it requires the latest versions of Safari or Chrome:
    As in our previous Webkit example, there are no images, and all animation is handled via CSS. Kiss my face!
    I can’t tell you what to do with all this information. But I do caution you about the potential misuse of your new powers. In the words of our friend Captain Planet, “The power is yours!”
    Use it wisely.