CSS Buttons using PNG transparency
This article is about using some basic CSS techniques and transparent png's as a basis of creating a consistent, low overhead, multipurpose button technique for modern browsers. There are techniques out there for making this method work even for browsers without proper png transparency support (read IE 6 here) however that is outside the scope of this article and should be no trouble for you to develop on your own with this technique under your belt.
The idea behind this technique is simple, we want to have nice modern web 2.0 buttons across our site which change colors on hover but are not image based, as image based buttons are not professional nor semantic. We are going to use the png transparency capabilities of modern browsers along with CSS pseudo-classes to make it work, so let's get to it.
Creating our button graphics
Our first step is to create our transparent graphics for the buttons in our graphics editor, I'll be using photoshop here, but of course the method can be recreated in any decent editor. Start off by making a 300px wide by 50px high tranparent background image. Next make your preferable button shape, here I'll be making a slightly rounded button (about 5px corner radius) and use a middle darkness gray color for your shape (here I'm using #a6a6a6 as a base) see figure to the right.
Next Ctrl-Click the shape window in the layers menu to select it, then create a new layer above the first, then go to Select -> Modify -> Contract and contract the selection by 1px, then on your new layer fill in this shape with white. You should have something like shown to the left here in figure 2.
Ok moving along, Cntrl-Click the white layer we just created to select it, then hide this layer, then highlight the original button shape layer we started with and hit Ctrl-x to delete this inner portion, see figure 3.
Next create a layer below the existing layers, call it base color or whatever you like, and fill it in with what will be the main color of our button, here I'm using #2b92cd. Then Ctrl-click again our inner white hidden layer to select it's outline, and with white as your primary color in your pallette grab the gradient tool, create a new layer above all the rest, and make a nice semi-gradient from the top of the selection to about the middle on our new layer, you should have something as shown in figure 4.
Now you should be able to see what the big picture is, the base layer is what we'll be using as our background-color in the css for the button, it is simply there now for reference. The background color will show through and with the png image above it will give us our nice smooth button gradient, of course we're not done with our image yet, but I wanted to make sure you're keeping up.
Next Ctrl-click again our inner hidden white layer to select it, then highlight (select that is) our base layer, Ctrl-x our selection on this layer to remove the inside of the button shape, as shown in figure 5. Then double click our base layer to bring up the effects dialog, go to Color Overlay and select the color of the background of the web page this button will reside on. In other words the purpose of the color overlay portion is to mask the portion of the button from the CSS background color we will be getting to shortly.
Now is where we can experiment on how our button will look, I created a layer called 'bg color' below all other layers, and a text layer with 'text' in it above all other layers, this is basically the setup of how your button will look once we slice it into html and CSS, so you can experiment with different background colors on the bg color layer and text fonts and colors on the text layer as shown in figure 6.
When you're done playing with your colors and have an idea of what you want for steady state and hover colors we can move on to slicing our buttons. I should say I've been kind of sloppy so far so now I'm going to align my button as near perfect as needed vertically and horizontally in the file. Then we need to slice the left and right portions of the button graphic for what amounts to a type of sliding door's technique we'll be using in our CSS, but first the slicing.
First hide the bg color and text layer, then select the entire image left side only so far as you want your text indent to be in the final button as shown in figure 7, here you can see I'm going in about 20px.
Now save your file if you haven't done so already! because we're gonna take 3 steps forward and 3 steps back so we don't want to lose any of our work so far. After you have saved your file go to Layer -> Merge Visible and then Image -> Crop. You should have what's shown in figure 8, then save this graphic as a 24-bit png with transparency. Call this image 'button_left.png'.
Next after you have saved the left side of the button hit Ctrl-Alt-z 3 times to take you back to when you selected the left side originally as in figure 7 do not cancel the selection we still need it then hit Ctrl-Shft-i to select the inverse of our left side. Similar as we did the left side now go to Layer -> Merge Visible and then Image -> Crop again, and you guessed it, save this image as a png-24 with transparency, and name it 'button_right.png'. You should have something similar to figure 9.
Next hit Ctrl-Alt-z 3 times again to take us back to our original image, save this and we are done with our graphic work and it's time to head on to the html and CSS we need to pull it all together.
Putting the code to work for our button
Now we need to create the html for our buttons, I want to keep this as simple as possible, the html for our button is shown below:
<a class="png_button" href="#"><span></span>Button Text</a>
As you can see the html is quite basic (obviously I'm using an example href here of # for demonstration purposes), the CSS is a litle trickier of course and is shown below with comments I will explain next.
a.png_button:link, a.png_button:visited {
background:#2b92cd url('../images/button_right.png') top right no-repeat; /* first the bg color then image */
font-size:24px; /* pic a reasonable font-size for the size of your graphic */
line-height:50px; /* make this the same as your image height */
padding:12px 23px 11px 0; /* these are our 'fudge' numbers for making the image size and font size work */
color:#5c6d9a; /* your font-color */
a.png_button:hover {
background:#000099 url('../images/button_right.png') top right no-repeat!important; /* your bg hover color here */
color:#fff!important; /* your hover font-color here */
}
a.png_button:link span, a.png_button:visited span {
float:left;
height:50px;
width:20px;
background:#2b92cd url('../images/button_left.png') top left no-repeat;
}
a.png_button:hover span {
background:#000099 url('../images/button_left.png') top left no-repeat;
}
Let's go over the main lines of the CSS here. First look at the a.png_button in static mode (the :link and :visited pseudo-classes ). Here we're using the shorthand notation for the CSS background property, the first value being the background-color, the second our image and finally our image alignment (top right for the <a> tag and top left for the embedded <span>). Next we define the font-size property, make this reasonable for your graphic size (and bear in mind my graphic in this example is HUGE for informational purposes to make the technique clearer). The line-height property must be the same as the image height, in this example 50px.
Next we see I have the padding property in short-hand notation as well (of course the 4 numbers in this notation are top, right, bottom, and left in order) these are picked by trial and error (I didn't say it was science after all) and depend upon the image height as well as font-size and line-height properties, and no there is no formula I could discern across browsers so bear in mind you may have to target IE in a seperate stylesheet. I suggest you start with a top and bottom value of about the image height minus your font-size, and a right value of roughly your button_right.png width, then adjust for fit (you'll see what I mean trust me). Finally you see we have our color property for our static font color.
Next take a look at our :hover pseudo-class for the a tag, the only two lines here necessary reflect the change in background-color (in our short-hand notation) and font color during the hover state.
Finally we examine the code for the <span> tags, since I've set them up as children of our <a> tag they can inherit the pseudo-class states from the parent tag in our CSS selector statement. First: the width and height properties are obviously the width and height of your button_left.png image, also the span has to be floated left to be taken out of flow and have the parent <a> tag run over it. The only thing left is to assign the background image to our span, and change the color property in our background short-hand notation to the analogous colors used in the defining of the <a> tag properties. Next, well, we're done!
You can see the technique in action below, note how the button background width gracefully accomodates the buttons text (to the extent of course you created your button_right.png graphic).
Conclusion
The reason behind going through all this trouble is simple, to create a single set of button graphics (only two here) to be reusable across a page or site, having different button colors available through only a minor change in CSS properties. The reward is that the users browser will cache the images and hence only need to download them once per page / site. This is in stark contrast to having a different image for each button on a specific page. If you are a developer you should easily be able to imagine numerous extensions of this basic method. Enjoy and keep it semantic!











