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.

Published May 05, 2009
Categorized as HTML and CSS
Short URL: http://snook.ca/s/946

Conversation

19 Comments · RSS feed
Chris Wallace said on May 05, 2009

You need to stop blogging so often. You're throwing me off man. Now I feel like I need to start blogging. And everyone will start blogging. And we'll end up with millions of bloggers. Is that what you really want??? Is it???

David Walsh said on May 05, 2009

I'm still hesitant to use browser-specific CSS animation features. I'm encouraged by WebKit's desire to push CSS forward but I'd much prefer that a standard be passed. A perfect example of why I dislike this type of implementation of CSS is the difference in border radius directives in each browser.

Mike T. said on May 05, 2009

I have to confess I too was a bit skeptical when the CSS transitions/animations started hitting the WebKit blog. But after doing a little experimentation--I'm liking them more and more.

As an example of (ridiculous) progressive enhancement, here's some polygonal CSS I was playing around with then decided to throw in some webkit magic:

http://www.miketaylr.com/CSS/shuriken

With or without the (admittedly wonky) animation, end users are still able to see the effect.

Karl G said on May 05, 2009

Imagine declaring this in JavaScript? How cumbersome.

var hoverAnim = partial(cssAnimation,"color:#333;",{duration:400});
forEach($$('a'),function(el){
connect(el,'mouseover',hoverAnim(el),'toggle');
connect(el,'mouseout',hoverAnim(el),'toggle');
});

Seems simple enough to me. Of course, that's using MochiKit and my animation library to make it work as simply as the webkit declaration, but declaring this stuff doesn't have to be hard.

Matt Puchlerz said on May 06, 2009

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

I too was unenthusiastic about CSS animations when they first appeared on the scene. Yet the more I think about them, and the more I consider the "we need change" opinions of people such as Matt Wilcox, I agree that defining animations within the presentation layer makes a lot more sense than within the behavior layer.

That said, I still find these new CSS properties somewhat awkward. Perhaps it's just lack of experience with them thus far.

Matt Wilcox said on May 06, 2009

I'm glad you've changed your mind on this, someone with a bit of impact having this viewpoint's good. I'm glad to see the technology gaining traction too. I've used CSS animations on a few recent projects, just as a bit of added niceness, and it's worked well. A favourite at the moment for thumbnail galleries is to define a hover-state transform of 1.1 and add a box-shadow, then animate them over half a quarter-second or so.

I've yet to suss out the best way of implementing these for the iPhone, an environment where most of the css "behaviour" psuedo-classes are redundant as a trigger (:hover for example). It feels a bit ironic that a CSS enabled device actually has little use for them. I can't wait for Firefox to get animations. Roll on 3.5, at least you have transforms if not transitions!

Robin Cannon said on May 06, 2009

Good article. I think I'm coming round to that way of thinking too. With options like Webkit it's becoming easier to provide increased functionality that, while it may not be cross browser, does give the best experience possible to a user and doesn't have a negative impact to others using different software. Of course, I'd love a consistent standard across all browsers, but then wouldn't we all? In the meantime I think it's great to be able to showcase design that's as good as a browser allows without breaking our display on different apps, rather than "dumbing down" to cater to the least advanced browsers.

Jonathan Snook said on May 06, 2009

@Chris Wallace: It's been nice to blog more frequently again. I enjoy it (and hopefully everyone else does, as well).

@David Walsh: I agree that I'd like the standard to make it to recommendation status but having subscribed to the www-style list, I know it's going to take time. I'd love to see FF4 or IE9 jump on this and get it implemented.

@Karl G: and you don't think that is cumbersome? In CSS, I can add one declaration. In JS, it'll require at least 4: retrieve DOM elements, for loop, add event handler, execute event handler. And what of the performance issues of adding that many event handlers to the page?

Darran said on May 06, 2009

Many of these effects are already in place, the WordPress caption is a fine example. FF shows as a rounded border, while IE shows it as a normal border. It hasn't yet become a standard, maybe in time it will but for now, it is in a huge mess. An alternative would be to use javascript libraries, they make things so easy for us.

Craig Wann said on May 06, 2009

Great post, though I think I will wait until we have better cross-browser support to implement CSS animations...

Michael Kozakewich said on May 06, 2009

Imagine my surprise when I found out Chrome 2 can do everything in CSS3 except the border colours (and speech, I'd suppose). There are a couple glitches with shadows and border images, but it's otherwise great.

It's going to take me a while to kick myself into using these styles in my daily work. I've looked forward to CSS3 for a while, now, but I can actually start using them today!

Pedro said on May 06, 2009

Would really help if you could add a Demo page to your Posts. Thanks anyway.

Jonathan Snook said on May 06, 2009

@Pedro: it seems unnecessary to add a demo page just to show off an a:hover or adding a class. However, if you click through on the very first link in this post, you'll see a bunch of demos. Likewise, if you're viewing this site in a recent browser, feel free to wave that mouse over the left nav or the about/work/contact links. They should magically fade in and out.

Sean McArthur said on May 06, 2009

I wanted to peak at how the transitions look, so I came here in Chrome... The fade seems backwards. Hovering the left links causes a fade, but it goes from green to transparent, which with now white text on hover, makes the links very hard to read :)

Karl G said on May 06, 2009

I'm not arguing that js animations are better, just that it's not unduly cumbersome. Trying to do a particular domain task in a general purpose c-like language is always going to be more code than doing something directly supported in a domain-specific language. The two solutions approach each other in complexity as your desire to control the animation increases. E.g. if you wanted two properties to animate at different rates, if you only want animation on mouseover but not mouseout, you want animations to cascade, etc.

What IS cumbersome is that my library is 800 lines/7.5k compressed and minified to get something that simple to work semi reliably and with reasonable perf. Most of that is hadling edge cases and I still didn't get rid of them all. The webkit CSS animations were basically what I was shooting for when writing the engine and I would certainly use CSS animations if I could ignore the market share that didn't support them simply because the edge cases are handled/documented and the browser has to do the bookkeeping.

As for perf, you do what you can with what you've got.

Nathan Nash said on May 07, 2009

Ah, so that's what makes your links fade so nicely as you mouse over them. Recently making the full on switch to Safari only on macs, I'm enamored with Safari 4, I'll be sure to enjoy the functionality of CSS animations. I'll have to look up the webkit transitions property.

Thanks for sharing!

Paul D. Waite said on May 07, 2009

> I'm still hesitant to use browser-specific CSS animation features. I'm encouraged by WebKit's desire to push CSS forward but I'd much prefer that a standard be passed.

Sure, but I think you tend to get at least one implementation before something becomes a standard. (I thought Eric Meyer wrote a great post about this but I’m buggered if I can find it now.)

XMLHTTPRequest, for example, started life as an ActiveX control, and that’s turned out pretty well.

ricardo said on May 14, 2009

Using jQuery UI you can achieve that keeping the styles in the CSS:

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

$('a').bind('mouseover mouseout', function(){
$(this).stop(true,true).toggleClass('hover', 1000);
});

Of course the native CSS anim will be smoother in more complex cases.

I can't remember where, but I've seen a library that attempts to implement css animations via javascript on browsers that don't support it.

custom nfl jerseys said on February 28, 2011

wow,maybe you are right,but i still have my own idea!

Sorry, comments are closed for this post. If you have any further questions or comments, feel free to send them to me directly.