Slick CSS Animations Without JavaScript

Recently I watched a video on Polymer animations. The video is a introduction tutorial using Polymer's animation library. The demonstration shows how to animate a login dialog's entrance, fade in and down. This is one of the first times I had watched a Polycast or studied Polymer in general. I was not impressed.

Polymer Animations

The video shows the Polymer animation library, which is a complete waste of precious bytes and abstraction. Instead of using this library, wasting your customer's bandwidth and time you should just use CSS animations. They are much more efficient to load and execute. All the polymer library does is write the CSS at run-time. Anytime I see code being written at run-time in the client I look to see if it should be generated at development time instead. In this case, absolutely.

I want to point you to a CSS library I use to build my animations, it is called Animate CSS. The library is a collection of turn key CSS, key-frame animations. I want to show you how to execute the exact same demo without polymer or much JavaScript for that matter.

Let's start by just animating the dialog in the same manor shown in the Google tutorial, fade in and down. Annimate has a keyframe named fadeInDown, which does exactly what we need.


@keyframes fadeInDown {
from {
opacity: 0;
transform: translate3d(0, -100%, 0);
}

100% {
opacity: 1;
transform: none;
}
}
.fadeInDown {
animation-name: fadeInDown;
}

That is pretty simple, not even that much CSS code to explain.

I realize many developers may not know what a key frame animation is so let me take some time to explain how they work. Key frame animations are not unique to CSS, they are used in just about all digital mediums. We see them in television shows everyday. Have you noticed promos sliding in from the bottom right teasing you with other shows on the network? Those use key frame animations.

If you have done any XAML programming and I assume ActionScript you have no doubt seen or written a key frame animation. The concept is pretty universal and has been around for a while.

A key frame lets you define what rendering properties apply at certain points in time. The animation runs for a set time, say 1 second (1000 milliseconds). The animation defines properties, CSS properties for the web, and their values at different times from the animation start through the end. So if you wanted the opacity to change from none to 1 like the example above you define what the values are at 0 and 100%.

You are free to add other frames to the animation. In the following code I added a frame at the 50% point, it sets the opacity to .4. Now the fade in is slightly slower for the first have of the animation duration and a little faster the second half.


@keyframes fadeInDown {
from {
opacity: 0;
transform: translate3d(0, -100%, 0);
}

50% {
opacity: .4;
}

100% {
opacity: 1;
transform: none;
}
}

This is a simple CSS key frame animation, you can make them much more complex, but you should see the basic idea. The Animate CSS library relies on a some classes being applied to the animated element. The common 'animated' class is the key, it defines the animation duration and the fill mode.


.animated {
animation-duration: 1s;
animation-fill-mode: both;
}

If you wanted a longer or shorter animation you can change the duration to another number. For example a 2 second animation would use 2s or 2000ms. You can use the millisecond time unit, ms, to give you more granular control.

The animation-fill-mode property is an interesting CSS animation feature. Without defining this property the animated element returns to its initial state, or it renders exactly the same as it did before the animation. The animation-fill-mode property has four possible values: none, forward, backward and both. To be honest you rarely see a different between forward and both. Backward and none are also almost identical. You can read more about this property in a Site Point article.

Another CSS rule causes the animation to infinitely loop. You can replace infinite with the number of times the animation should repeat before it ends.

.animated.infinite {
animation-iteration-count: infinite;
}

CSS Animations

The Markup

My example is very simple, but mimics the login dialog shown in the Polymer video. A Login button is centered at the top center of the page. When the user clicks or taps the button the login dialog fades in from the top, sliding into place. The login button fades out.

The login dialog is just a vertical list with a username and password field followed by another login button. When the dialog's login button is pressed the dialog flies up and fades from view and the original login button fades in.

Notice how the login button and the login-dialog elements have the animated class. This is the core CSS class that drives the animate.css library. The login button also has the fadeIn class applied. This causes it to fade in as the page renders. The dialog's inital opacity is set to 0, hiding it from view.


<button type="button" class="btn btn-success btn-show-login animated fadeIn">Login</button>

<div class="login-dialog animated">
<ul class="vertical-list">
<li>
<label>Username:</label>
<input type="text" name="username" value="" />
</li>
<li>
<label>Password:</label>
<input type="password" name="username" value="" />
</li>
<li><button type="button" class="btn btn-success pull-right btn-login">Login</button></li>
</ul>

</div>

The JavaScript

I chose to write the JavaScript long hand so you can see exactly what is happening. In a production application I would use my DollarBill library and the addClass and removeClass functions to reduce some of this code. DollarBill is a micro version of jQuery.

The first section just gets references to the two login buttons and the dialog element. Next I bind a callback to the button's click events.


var showLogin = document.querySelector(".btn-show-login"),
loginDlg = document.querySelector(".login-dialog"),
loginBtn = document.querySelector(".btn-login");

showLogin.addEventListener("click", function () {

loginDlg.classList.add("fadeInDown");
showLogin.classList.add("fadeOut");
loginDlg.classList.remove("fadeOutUp");


});

loginBtn.addEventListener("click", function () {

loginDlg.classList.remove("fadeInDown");
loginDlg.classList.add("fadeOutUp");
showLogin.classList.remove("fadeOut");
showLogin.classList.add("fadeIn");

});

In the showLogin click event the fadeInDown class is applied to the dialog element and the fadeOut class to the login button. The fadeOutUp class is also removed from the dialog just in case it has been applied by a previous cycle.

Conversely when the dialog's login button is clicked the dialog has the fadeInDown exchanged for the fadeOutUp class and the login button has fadeIn swapped with fadeOut.

That is all you have to do, simply add and remove class references from your animated elements. No real JavaScript driving the animation effects.

Summary

While fast food frameworks like Polymer seduce many developers to a lifestyle that sacrifices user experience for a certain geeky coolness they add no value. All browsers support CSS animations and wonderful experiences can be created with little to no script by applying CSS class references on specific elements.

Polymer's animation library is big and bulky so it can write inline styles at run-time. This run-time calculation is CPU intensive and can be avoided by creating the CSS at development time, not real-time. Creating the animation once is much more efficient than every time it is invoke.

Animate.css is a good turn-key reference library you can use as is or as a reference to create custom animations. These animations can be applied to your markup by adding and removing CSS classes as needed to drive your animation.

Using pure CSS animations creates a much more maintainable user experience that runs more efficiently. This pays off exponentially on mobile class devices, making your customers happy. When your customers are happy your stakeholders and happy, thus making you happy.

You can download clone the example source code from my GitHub.

Share This Article With Your Friends!