Monday, February 4, 2008

The Amish Will Hate These Buttons

I've always heard that the Amish have an aversion to buttons, although it could just be a rumour. A quick check of Wikipedia shows that indeed, some Amish dress codes prohibit the use of buttons on clothing because of their (the buttons, not the Amish) association with the military and their potential for vanity. Well, OK. For those of you Amish who have accidentally stumbled across the least read blog on the planet, please divert your attention by clicking on any of the Google Ads to the right. We are about to get downright vain.

Same Old Song and Dance

I was recently in need of adding some buttons to a web page I was designing. They weren't actually the typical command buttons like cancel or submit. They were acting as special toolbar buttons on my page and needed to be very graphical. They were also going to need to change color to indicate disabled and enabled states. The application is international, so the buttons would have to scale horizontally to accommodate differing text widths.

We've all seen this trick a thousand times, and its been documented to death. Here is a link to a popular article on the subject. I opened Photoshop and began to "draw" the button I had envisioned. It was a rounded rectangle with some Photoshop effects applied to achieve a green gradient background with the obligatory button shading.

normal_button

layers_normal_button

Normally, I would copy this button and change the colors used in the gradient overlay to achieve a button with different colors for the different states of a button; rollover, disabled, and clicked. In the end, I would have four different button images and I would swap them out using a little JavaScript and CSS. (I could also opt to combine the images into a single large image and swap them using only CSS. There are a hundred ways to skin this cat.)

A New Perspective

I soon began to get bored with my options. I mean, how brain dead is it to keep swapping out these static images to respond to user interaction. Taking a cue from the Aqua Look and Feel and the work Kirill has done with the Substance Look and Feel, and the way every game console works, I realized that smooth transitions between button colors simulates the way natural light refracts on a normally translucent is simply cooler. A smooth transition from one color to the next can be achieved in HTML in two ways, AFAIK.
  1. Create two elements, one with the starting color and one with the ending color. Make the ending color element have an opacity of 0 and align it on top of the starting element. In response to mouse events, animate the opacity of the ending color element to achieve the effect.
  2. Using a single element, animate the background color from one color to another.

I think you might guess which approach I took. :-) Animating background colors from one value to another is a simple task in the RGB world.

rgb_transition

Each unique color is comprised of a unique combination of red, green, and blue values ranging from 0 to 255. An example starting color may be bright green with a CSS color setting of rgb(0, 255, 0), and an ending color of bright blue with a color value of rgb(0, 0, 255). In order to animate along the path shown in the graphic above, we perform a linear transition of each individual color component. For each step in the animation, red will range from 0 to 0; green from 255 to 0, and blue from 0 to 255. You can see that half-way through the animation, our color is rgb(0, 128, 128).

Color Cubes - A Peek Under the Covers

It's worth pointing out that the small graphic above is a very simplified 2D view of color space. The path denoted by the arrow doesn't even exist in the RGB color space (although it does exist in the HSB space).

color_cubeThink of the RGB space as a cube with one corner of the cube representing black (0, 0, 0) and the opposite corner is white (255, 255, 255). The three axis emanating from black are the red, blue and green axis. In the diagram below, I've filled in the left side of the cube with the representative color gradient.

green_blue_squareNext is a 2D view of the same side of the color cube. You can see that the path denoted by the line shows the color range that is traversed by our linear transition.

 
Let's see an example. If you press the transition button, the box on the right will animate between green and blue.

Your opinion may differ, but when this transition occurs, I would prefer that the color hues change and the saturation and value not change. This is achievable by converting from RGB to the HSL color model. Then the hue can be transitioned from one color to another without an artificial darkening or lightening step. Of course, the HSL color values will have to be converted back to RGB in order to apply them to the element. In CSS3, HSL is supported as a valid color model, but only Firefox 2 and Safari 3 offer support.

Finishing it Off

Now that we are achieving a smooth transition from one color to another, it is a relatively simple matter to compose a translucent image that sits over a div with a changing background color. The image will allow the background color to shine through with varying opacities. In order to pull this off, the image will have to be a PNG, of course.

It's a bit trickier to create these images in Photoshop which is mostly due to the way effects are applied in the tool. You will find yourself creating a lot of the affects as grayscale gradients on separate layers and varying amounts of opacity.

Here are shots of a portion of the new button with its background color and one without the background. On the translucent image, you can barely make out the subtle shading. It is most helpful to work with a background color to bring out the detail. When you save the image, save it without the background and as a transparent PNG.

new_button_trans The transparent image appears with several layers of gradients and borders. They're subtle, but they are there.

new_button The gradients show up nice against an opaque background.

layers_new_button Here are the Photoshop layers. Notice the Matte layer; this is the solid color in the corners. The matte is necessary for this particular example because the background color would show through otherwise. With a rectangular button, this would not be necessary.

Putting it all Together

Here are a couple examples. I am using the jQuery library to provide the color animation capabilities and event handling, but they can be performed with nearly any library or you can roll your own. Buttons that react to user events with smooth and elegant transitions are not just the realm of Flash and custom toolkits.

Who Needs Flash?

You can also add color transitions on mouse up and mouse down also. Try it out.