Creating Buttons With CSS

Web Review
February 1999

As a Web designer, odds are that at some point you've used the classic links-down-the-side interface: a page title across the top, the content below that, and down the left side (usually) you put a column of buttons. This approach has been used by nearly everyone from CNN to Microsoft to, well, Web Review.

In some cases, you may have decided that you were better off using just plain text links, since they're easier to fix if there's a spelling error, not to mention easier to change or add. If you need a new button, all you have to do is type it in, not create it in something like Photoshop. And, of course, you don't have to worry about button length that way. With graphic buttons, they all have to be the same width, or else they start to look dumb. If you add a new button that's wider than the others, then you may have to go back and widen your old buttons-- and that's just a pain.

With CSS, however, you can get the best of both worlds... assuming you're willing to put a little thought into accounting for browsers which don't support CSS as fully as we might like. By using the background properties of CSS, you can have buttons which scale themselves to whatever size is needed, and have interesting decorations, all at the same time, like these:

Doing It Right

For the moment, let's assume that all browsers support CSS1 fully, and explore the simplest way to get the effect we want. In this case, all we need to do is set up each button like this:

<TR>
<TD class="cap"><IMG SRC="buttoncap.gif"></TD>
<TD class="text">Button #1</TD>
</TR>

This causes the image "buttoncap" (the rounded end of the button) to be placed in one table cell, and the text of the button in another, both in the same row. The classes are there for effects which we'll see in a moment. Without any CSS, and with the row's borders turned on, the above markup would look like this:

Button #1

All right-- so far we have two pieces, which are the button's text and the graphic buttoncap.gif. We need another cap to finish off the button. However, in this case we want to put the second cap into the background of the cell with the text in it.

We can do this with CSS, of course. Given the image buttonbg.gif, we can place it on the right side of the text cell's background like this:

TD.text {background: white url(buttonbg.gif) top right no-repeat;}

...but that, unfortunately, will get us the following:

The problem is that the background image has been placed right under the text. This is correct behavior, of course, but visually it's a mistake. Therefore, we need to set some extra space. Since buttonbg.gif is about 17 pixels wide, we can get an interesting effect by setting the right padding of the text cell to 10px. This will make the text look as though it's hanging into the cap, so to speak. This requires the following styles, and gets the following result:

TD.text {background: white url(buttonbg.gif) top right no-repeat;
     padding-right: 10px;}

We could add other styles for the font and its alignment, of course, but first we need to confront a more pressing issue. In order to achieve this effect, we've positioned the background image top right. That's fine so long as a browser supports the positioning of background elements, but what if it doesn't? This is an important question, since Navigator 4 doesn't support such positioning, so you'll see this instead:

Oh, gross. Now what?

Well, this is why I chose to slice up the caps the way I did. By adding a second bit of padding to the text cell, we can leave room for the offending cap, thus leading to the following:

TD.text {background: white url(buttonbg.gif) top right no-repeat;
     padding-right: 10px; padding-left: 20px;}

And there you have it. Almost.

More Browser Pain

Now that we've managed to work around everything, we find that life isn't quite so accommodating. For example, that last set up markup there will produce the following in Explorer 4.5 for the Macintosh:

So it's back to the drawing board. Most of our troubles seem to be centered around assigning properties to table elements (e.g., TD), so maybe we need to stop doing that and find another approach. Given the various browser bugs and other issues, it might be best to revive the idea of graphical buttons, but not in the same way.

Instead of creating buttons which are just one big graphic, we'll stick with our button caps, and create graphical button text. If we set them up correctly, and use transparent backgrounds for the buttons, we should get very similar results.

In your favorite graphics program, such as Photoshop, create each button with the appropriate colors (whatever works for you). Ensure that the background is white, and that you have 10 pixels of white space on the right side of the text and 20 pixels of white space on the left. Also, you need to make sure that th images are as tall as the buttoncaps, which in my examples are 25 pixels tall. Then save the text as a GIF image with the white pixels set to be transparent. This should give you something like this:

Now we alter the styles and markup to get the following:

TD.text {background: white url(buttonbg.gif) top right no-repeat;}

<TR>
<TD class="cap"><IMG SRC="buttoncap.gif"></TD>
<TD class="text"><IMG SRC="text.gif"></TD>
</TR>

As you can see now, we've gotten roughly the same effect, although we had to drop the text to do it. While this is less in the spirit of CSS, and it will increase download times a bit, these do have the advantage of allowing for exact styling of the button text, not to mention Javascript-driven highlighting and other such frills. In addition, you get the following looks, depending on your browser:

While they're not exactly the same, at least neither case looks like a complete mistake.

This month's excursion into CSS has been interesting, to say the least, given that we started with a nice text-based effect and managed to end up with a heavily graphics-based solution with a reduced use of CSS. Unfortunately, browser incompatibilities will do that to you. In general, the main point here is that if you're going to use techniques like those described in this month's column, you need to think through your approach carefully, and make sure that browser bugs won't completely wreck what you're trying to do.