Giving Animations Life

Using Bounce.js and classical animation concepts to bring life to user interfaces.

Joel Besada
Tictail  -  Behind the Scenes

--

I love animations. That’s why I created Bounce.js, a tool and JavaScript library for generating beautiful CSS3 keyframe animations. In this post I want to show how you can use Bounce.js, and some concepts from classical animation, to bring life to your animations in your web apps. I’ll begin with a regular boring animation of Tictail’s signup form flying into view and advance step by step to create something more interesting. Note that each GIF also has a link to a higher quality video to better see the details.

First Iteration — Default Ease

View MP4

This first version is just a regular, hand-written CSS3 keyframe animation with only two keys:

.form {
animation: form-fly-up 0.35s ease;
}
@keyframes form-fly-up {
0% { transform: translateY(500px); }
100% { transform: translateY(0); }
}

I’m using the default easing function, ease, which slightly slows down the movement before halting to an end. This is probably the simplest form of animation that you can create, and it doesn’t look all that great. The motion is very unnatural and feels robotic and stale.

Second Iteration — Bounce Back

View MP4

To spruce things up a little, let’s add another key to our keyframes to make the signup form overshoot a small distance before settling in its final position:

.form {
animation: form-fly-up 0.45s ease;
}
@keyframes form-fly-up {
0% { transform: translateY(500px); }
50% { transform: translateY(-50px); }
100% { transform: translateY(0); }
}

This gives more of a “springy” feeling to the signup form, but it’s still a bit awkward. I could spend time on tweaking the values, or even adding in more back and forth bounces, but wouldn’t it just be better to have a computer calculate the keyframes for us based on a real physical model? That’s exactly what Bounce.js does!

Third Iteration — Spring Physics

View MP4

Here I’ve used an animation generated by Bounce.js. It’s probably the most basic animation the tool can create, but it’s already feeling a lot better than before!

.form {
animation: form-fly-up 1s linear;
}
/* Generated with Bounce.js. Edit at http://goo.gl/AUAzKV */
@keyframes form-fly-up {

}

I’m using the default bounce easing function, which is based on a simplified model of a mass-spring-damper system. Special thanks to Soroush Khanlou for his blog post explaining them and his iOS library, SKBounceAnimation, which has been to great help in creating the easing functions for Bounce.js.

Now that we have the fly-in motion in place, let’s think about other ways to improve the animation even further. A good source of inspiration is animated cartoons, and the concepts and tricks that animators use to create them.

Disney’s Twelve Basic Principles of Animation is a set of principles for producing more realistic animations based on the work of leading Disney animators during the golden age of animation. The principles were introduced in The Illusion of Life: Disney Animation, which has by some been referred to as the Bible of animation. Let’s examine them and see how we can apply some of the principles to our signup form here.

Fourth Iteration — Follow Through and Overlapping Action

View MP4 (+ Slow Motion)

Follow Through and Overlapping Action are two related techniques that help give the impression that animated characters or objects follow the laws of physics. In essence, they show that different parts of an object may move at different rates during motion, or continue moving after the motion of the main object has stopped.

In the animation above, you’ll see a couple of frames of the button moving independently after the form has stopped. This gives the illusion of the button being a separate object with its own weight, rather than the entire form feeling like it’s just a flat, rigid paper card.

.form {
animation: form-fly-up 1s linear;
}
.button {
animation: button-bounce 1s 0.12s linear;
}
/* Generated with Bounce.js. Edit at http://goo.gl/TvjpS6 */
@keyframes form-fly-up {

}
/* Generated with Bounce.js. Edit at http://goo.gl/sNmGrx */
@keyframes button-bounce {

}

Note that the stiffness of the form-fly-up animation has been increased to give it a harder impact, which emphasises the motion of the button more.

Fifth Iteration — Animation Smear

View MP4 (+ Slow Motion)

In this next iteration I’m stretching out the entire form while it’s moving (see the video in the caption for a slowed down version), to simulate a motion blur. This is called an animation smear and is not directly from Disney’s twelve principles, but is nonetheless a common and useful trick used in hand drawn animation to reduce the number of frames required to convey a motion. This tumblr blog is dedicated to collecting and displaying still frames of animation smears, and it really showcases the craftsmanship that can go into creating this effect.

Note in the code below that we’ve changed the transform origin of the form to be at the top instead of the default center, so that it stretches away from the direction of the motion.

.form {
transform-origin: 50% 0;
animation: form-fly-up 1s linear;
}
.button {
animation: button-bounce 1s 0.12s linear;
}
/* Generated with Bounce.js. Edit at http://goo.gl/dvi8wI */
@keyframes form-fly-up {

}
/* Generated with Bounce.js. Edit at http://goo.gl/sNmGrx */
@keyframes button-bounce {

}

Now, since our computer already does all of the drawing, my added smear doesn’t really serve the purpose I described above. However, smears can still be used for the artistic effect, or for the exaggeration of a motion, which is the reason for using it here. This actually leads us back to the twelve basic animation principles again, since exaggeration is one of them.

Final Iteration — Squash and Stretch

View MP4 (+ Slow Motion)

In this final iteration of the animation, I’ve used what is described to be “by far the most important” of Disney’s twelve principles — Squash and Stretch. This principle is used to give a sense of weight and flexibility to objects. A classic example of this is a bouncing ball compressing as it hits the ground and then extending as it bounces up again:

Image by Autodesk

To get the desired effect on our signup form, it’s important to try to maintain the overall volume as it squashes together on its impact.

.form {
transform-origin: 50% 0;
animation: form-fly-up 1.29s linear;
}
.button {
animation: button-bounce 1s 0.12s linear;
}
/* Generated with Bounce.js. Edit at http://goo.gl/G1h7Qa */
@keyframes form-fly-up {

}
/* Generated with Bounce.js. Edit at http://goo.gl/sNmGrx */
@keyframes button-bounce {

}

Now that we’ve reached the final version of the animation, I’m sure you’ll agree that I’ve made it look very cartoony, which might not necessarily be the look you are going for. Keep in mind however that I’ve opted for a more extreme portrayal of the different principles just to make the point clearer. All of the principles described above can be used in a more modest manner to get something that fits better with the rest of your style.

I think that we as user interface designers and developers have a lot to learn both from classical animation and physical models to make our animations feel better. I hope this post has been able to demonstrate the interesting things that can happen when both of those worlds are combined, and I’m excited to see all the projects that have come out lately that are simplifying the process of animating for the web. With the increased browser support for performant animations and more people starting to work with them more seriously, I would like to believe that we are about to enter the golden age of web animation.☺

Thanks again to Soroush Khanlou for his wonderful work on SKBounceAnimation. Thanks also to Pasquale D’Silva (@pasql) for pointing out improvements to some of the animations — If you haven’t already, you should totally check out his post Transitional Interfaces.

--

--

Joel Besada
Tictail  -  Behind the Scenes

Software indie | Previously engineer @Shopify (Shop app), @tictail | Also building things at @MinMaxGG