May 2009
Mon Tue Wed Thu Fri Sat Sun
« Apr   Jun »
 123
45678910
11121314151617
18192021222324
25262728293031

Day 05.05.09

Twitter Updates for 2009-05-05

Bacon REALLY does cure a hangover! http://tr.im/kxR8 #

Shifting my Opinion on CSS Animations

When CSS animations were first introduced in Webkit back in 2007, I expressed my concerns that CSS may not be the best place for it.

Sound cool? I don’t think so. Not only does it make CSS more complicated, it makes JavaScript more complicated, too.

Having actually taken some time to implement CSS animations in an example, a light bulb clicked. The way I looked at how animations were declared and in what situations you would declare them suddenly changed. I believe I have done a 180 on this. Why and how, you might ask?

Understanding Transitions

The first hurdle for me was understanding how animations were declared. Where do you define them? How do you set the type of animation, the duration, and what should happen? What finally clicked is not that I’m defining an animation.

I’m defining that when an element (based on the CSS selector) has a style property change, that the change happens gradually instead of instantly.

When I looked at it in this way, it was no longer about JavaScript or behaviour, or anything else but simply defining that property changes shouldn’t be instant.

Here’s a quick example:

a { color: #039; }
a:hover { color:#333; }

I’m sure you’ve seen code like this a zillion times. But what if you wanted the property change to be gradual?

a { color: #039; -webkit-transition-duration:.4s; }
a:hover { color:#093; }

Try this in Safari 4 and you’ll notice some really nice soft fading between the two states. Imagine declaring this in JavaScript? How cumbersome.

Separation of Presentation

Which made me make the connection to the separation of content, behaviour and presentation.

One thing I’ve advocated for awhile is representing state changes within JavaScript by changing an element’s className instead of changing numerous style properties. For example, let’s say you have a bunch of tabs and you want to indicate that a particular tab is the active tab. The easiest way to do that is to attach a click event handler to a tab and then apply an active class to it (while at the same time removing the active class from any element that may already be active).

If the active tab was to be 10 pixels higher, then it’d be easy enough to declare this via CSS:

.tab { position:relative; top:10px; -webkit-transition: top .4s; }
.tab.active { top:0; }

When the active class is applied to the tab, its position is automatically transitioned from 10px to 0. In this case, I also explicitly indicated that the transition should only apply to the top property.

Detecting when an animation is complete

One of the other hesitations I had with CSS animations was the uncertainty of how animations would conflict with other JavaScript code that may be running at the same time. As I understand it, inspection midway will report accurate computed styles at the point of animation.

To detect whether an animation has completed, you need to be on the lookout for the transitionEnd event which fires on the element that was transitioned. For now, the event needs to be prefixed with webkit, which is a little unusual in the world of JavaScript.

myElement.addEventListener('webkitTransitionEnd', myFunction);

Progressive Enhancement

Finally, one of the things that I like about this is its ability to be applied quickly while still allowing the same interaction in all other browsers, albeit minus the animation — an animation that is purely presentational in this case.

I don’t believe this is the solution for all browser animations. Far from it. While more complex animations can still be handled via JavaScript, I like the declarative way of describing that an element’s properties are transitionable.

I’ve seen plenty of people jump on the text-shadow, box-shadow, or rgba bandwagon. I now see transitions as being yet another tool to soften the experience for a segment of your visitors.

While I was reluctant to see this gain traction, I’m much more receptive to it now and would like to see other browsers get this implemented.