Bringing Styles Into the 4th Dimension
In the old days, in order to make HTML look the way you wanted, you used more HTML. Every element had to be individually styled, using ribbons of FONT and CENTER and B tags. Then CSS came along and gave web developers the ability to group elements into classes with similar display characteristics. The world heaved a sigh of relief, and developers started making more complicated websites, confident that site styling would not get in the way of functionality.
Then JavaScript and AJAX became popular, and suddenly it became commonplace for elements to have their classes modified by JavaScript, based on the results of AJAX calls from the server. When an element’s class changes, it is updated instantaneously to reflect the styles associated with the new class. That’s fine for some stuff, but sometimes you want the transition between classes to be a bit more, um, classy. Let’s say your site has a login box that remains hidden on a page until a user clicks the “log in” link. If you switch the box’s style from opacity: 0; to opacity: 1;, it will appear right away by default. If you want it to fade in, you have to write a JavaScript function that increments the opacity bit by bit until it reaches 1, and you have to call that function at the same time as you change the class of the login box. If you have a bunch of login boxes on your site, you have to attach that transitional behavior to each one of them manually. Because CSS doesn’t have the concept of transitioning through time, animation-heavy websites are stuck in the same place that pre-CSS websites were before CSS came along.
CSS transitions solve this problem by bringing styles into the 4th dimension. CSS transitions allow web developers to specify that if an element has its style modified, the browser should smoothly transition its appearance to the new style, rather than shifting it abruptly. They’ve been available in WebKit for about two years now, and just appeared in Gecko a few weeks ago. Since they’re not available in most browsers, webOS developers are among the privileged few who can take advantage of them. Here’s how.
The Basics
Suppose your login box is 300px wide and you want it to hide offscreen until a user clicks a link, at which point it should get the class active and appear onscreen.
#loginbox { width: 300px; position: fixed; left: -300px; } #loginbox.active { left: 10px; }
Here’s a version of that with transitions:
#loginbox { width: 300px; position: fixed; left: -300px; -webkit-transition-property: left; -webkit-transition-duration: .5s; -webkit-transition-timing-function: ease-in; } #loginbox.active { left: 10px; }
And here’s how it’d look if you wanted the box to fade in and slide in at the same time:
#loginbox { width: 300px; position: fixed; left: -300px opacity: 0; -webkit-transition-property: left opacity; -webkit-transition-duration: .5s .25s; -webkit-transition-timing-function: ease-in linear; } #loginbox.active { left: 10px; opacity: 1; }
Here’s a brief overview of the three -webkit-transition properties used above;
- -webkit-transition-property
- A space-seperated list of the properties that should be animated when they change. You should only use numerical properties. “top”, “width”, “border-width” and “opacity” work, but “display”, “text-decoration” and “list-style-type”, for instance, do not. If this property is omitted, all the properties of an element will be animated. This is probably not what you want.
- -webkit-transition-duration
- A space-seperated list of the durations of the transitions of the different objects. “s” stands for seconds. This is 0s by default, so you need to set it.
- -webkit-transition-timing-function
- From the W3C Working Draft:
The ‘transition-timing-function’ property describes how the intermediate values used during a transition will be calculated. It allows for a transition to change speed over its duration.
“ease-in” starts slowly and picks up speed at the end. “linear” keeps the same speed all the way through.
And here are some things that aren’t supported in webOS (as of 1.2.1), but probably will be eventually, since they are part of WebKit 4:
- -webkit-transition-delay
- Allows you to set a delay before the start of the animation.
- Events
- Currently, there’s no way respond when a transition animation finishes, and this is the main drawback of the CSS approach to transitions. WebKit 4 lets objects listen for animation events, which will let you string a bunch of animations together without needing to call setTimeout() to activate each part of the animation.
In addition to the reduced code clutter, CSS transitions can speed up your app, since they are run from native compiled code, rather than from interpreted JavaScript. Don’t expect miracles, though — I’ve found that webOS can only handle a few animations at one time before things get choppy, and the size and complexity of the elements being animated also makes a difference. I was unable to animate a 320×480 image without choppiness. While there is no programmatic way to cancel the animations, they are smart enough to smoothly reverse themselves if an element’s properties change in the middle of a transition. If the active class is removed from our login box while it’s still sliding in, it will slide out starting from wherever it happens to be at the moment the class was removed.
For more on the basics of transitions, check out the W3C docs, and keep in mind that all the properties should be prefixed with -webkit- in webOS.
Advanced Tricks with -webkit-transform
There’s another advanced CSS property in webOS, called -webkit-transform, that, when combined with CSS transitions, allows for some neat stuff. -webkit-transform is…well, I think of it as a mini-CSS within CSS. It lets you apply transformations to an element after it’s been rendered. In webOS, The available transformations (to my knowledge) are translate, scale, rotate and skew. To scale an element to twice its height and rotate it 30 degress (something that’s been impossible in HTML until now!), do like this:
#myDiv { -webkit-transform: scale(2, 1) rotate(30deg); }
The crucial difference between scaling a div with -webkit-transform and scaling by manipulating its width and height is that -webkit-transform will scale (or skew or rotate) the entire rendered div and its children smoothly. For more on -webkit-transform, see this post at Art of Web.
You can animate -webkit-transform by passing it to -webkit-transition-property. If you’re using a WebKit browser, hover over the card below to see an example.

#cardexample { -webkit-transition-property: -webkit-transform; -webkit-transition-duration: 1s; -webkit-transform: rotate(0deg) scale(1, 1); } #cardexample:hover { -webkit-transform: rotate(180deg) scale(1.5, 1.5); }
Our games Word Ace and Card Ace use this technique for pretty much every animation in the game. It’s a lot of fun to describe the behavior of a class in CSS and have elements automatically move around when they’re changed. There were times when I’d forgotten that I had set transition properties on an element, and was surprised when it started moving around of its own accord.
Caveats
Advanced animations are tricky with CSS. For example, the timers in Word Ace and Card Ace use transitions. In order to start a timer countdown, the yellow timer bar gets two classes set: one to set the bar to “full”, and another that sets it to “empty” with a transition, so that the width of the bar decreases slowly. My first pass at the code was something like this:
// CSS #timer-bar.full { height: 22px; background-color: yellow; -webkit-transition-property: width; -webkit-transition-duration: 10s; width: 100%; } #timer-bar.full.counting-down { width: 0%; }
// JavaScript function startTimer() { var timerBar = $('timer-bar'); timerBar.addClassName('full'); timerBar.addClassName('counting-down'); }
It didn’t work. The timer bar never went to “full”. After some research, I discovered a blog post explaining that changes to element styles are batched during an event, and are processed all at once after an event has finished, for performance reasons. In this case, WebKit sees that the classes I’m adding would set the element’s width twice, so it only bothers setting the second width — 0%. If you need to do a multi-step transition this way, you need to chunk the DOM manipulation into different events:
function startTimer() { var timerBar = $('timer-bar'); timerBar.addClassName('full'); setTimeout(function() { timerBar.addClassName('counting-down'); }, 0); }
Tricky, huh? This also applies in cases where you need to set a hidden element to display: block; before you move it around.
In Short…
CSS transitions make our games smoother, more lively, and easier to maintain. They’re not without their pitfalls, but once you master the basics, they’re an easy, elegant way to add a bit of zest to your UI. For more information (not all of which applies to webOS, unfortunately), see the Safari reference and the W3C working spec.
Dan Kurtz is the webOS developer at Self Aware Games, makers of Word Ace and Card Ace for the Pre and Pixi. Both are online multiplayer card games that make extensive use of the advanced JavaScript and CSS techniques available in webOS.


CSS implementation in webOS is pretty buggy (I wonder if this is really webkit, never seen a webkit-based browser with so many CSS and Canvas bugs…). The “opacity” CSS attribute does not affect text. So if you want to fade-in and fade-out some text with CSS transitions then you can’t use “opacity”. But you can use “color” instead:
#test
{
color: rgba(0, 0, 0, 0);
-webkit-transition: color 1s ease-in-out;
}
#test.visible
{
color: rgba(0, 0, 0, 1);
}
@kayahr omg, you safed my night, thx. I was trying to animate opacity for a text on my pre for hours.
[...] Pre101: A Guide to CSS Transitions in webOS [...]
[...] http://pre101.com/blog/2009/11/10/a-guide-to-css-transitions-in-webos/ [...]