Styling buttons to look like images with CSS3

For the first time in ages I was asked to code up some buttons that at first looked as though they could only be generated by using images. The buttons needed to allow for varying text lengths so my mind first went to the Sliding doors of CSS that I used to use regularly.

It was written in 2003! This is what happens when you’re from the olden days, in relation to web standards. I dismissed this immediately due to the fact it requires two elements to act as hooks (I only wanted to use button) and I knew there were CSS3 properties that could do all this. My worry was how many people would end up seeing the most fancy button.

The Photoshop image

Original photoshop button image - 'Update information'

This demonstration uses live CSS so in order to see the full effect you will need to be using recent versions of Mozilla or Webkit browsers. IE users will only see a very basically styled button.

Progressive enhancement

First start with the CSS for those browsers that don’t yet support CSS3 to make sure everyone can see the content inside the button.

button {
    background: #e4365b url(btn-bg.png) repeat-x bottom right;
    border: 3px solid #f2f2f2;
    color: #fff;
    font-family: Helvetica, Arial, sans-serf;
    font-size: 14px;
    font-weight: bold;
    padding: 8px 21px 5px;
}

Specify a background-color even though you have an image, so that the button text is visible when images are turned off:

And you have the gradient effect when images are on:

background-image: linear-gradient

The theory behind gradients can be found on the W3C’s site. There are more alternatives than linear and this value can be used wherever an image is applicable.

Put simply (without explaining vendor specific implementations) you first specify the direction of your gradient, in this case -90deg. After that you have a comma separated list of colours that dissect that line with percentage values of where you would like them to be placed.

I find this syntax difficult to put together myself so I generated mine using Galarza for the -moz prefix and Westciv for the -webkit prefix.

The code to get the gradient working in all browsers, except Opera (yes even IE using a filter!) is:

button {
    background-image: linear-gradient(-90deg, #d80f56 20%, #850934 90%, #850934 5%);
    background-image: -moz-linear-gradient(-90deg, #d80f56 20%, #850934 90%, #850934 5%);
    background-image: -webkit-gradient(linear, 0% 20%, 0% 90%, from(#d80f56), to(#850935), color-stop(0.9,#850935));
    filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0, StartColorStr='#d80f56', EndColorStr='#850935');
}

The gradient now takes precedence over the background image. If you don’t need to support Opera, then remove the call to the background image and save an HTTP request.

border-radius

To give the rounded corners of the button, add the border-radius property.

button {
    -moz-border-radius: 10px;
    border-radius: 10px;
}

As of Firefox 4 you no longer need to use the vendor-specific prefix of -moz, but I have kept it in as it will still be supported during a transitional time and older versions of Firefox will still require it. Webkit based browsers dropped the -webkit prefix as of version 3. IE6, 7 and 8 will get square corners.

background-clip

In the button above we are getting the button’s background colour bleeding out behind the corners.

Half button showing bleeding edges

By default the background colour is painted all the way under the border and would be specified as background-clip: border-box;. There are two other values this property can have padding-box and content-box, where the background is painted up to the padding and content respectively. In this situation we want padding-box.

button {
    -moz-background-clip: padding;
    -webkit-background-clip: padding-box;
    background-clip: padding-box;
}

Note that for Mozilla based browsers the property is padding. IE6, 7 and 8 do not support this property which isn’t a problem as they don’t get the rounded corners that this is solving. According to Quirksmode, Opera 10 is ‘almost’ compatible. They also say that Firefox below 4 doesn’t support it, I have only tested the property and value shown above.

Here is the button with the clipped background:

box-shadow

The final step is to add the drop shadow, this is added using box-shadow:

button {
    -moz-box-shadow: 2px 2px 3px #888;
    -webkit-box-shadow: 2px 2px 3px #888;
    box-shadow: 2px 2px 3px #888;
}

CSS3:info has a detailed page on understanding box-shadow. Once again, IE6, 7 and 8 do not support this property. Firefox, Safari and Chrome still require the vendor prefixes as shown above.

The final CSS button

To compare with the original image:

Original photoshop button image - 'Update information'

This is a perfect example of progressive enhancement and how we should start to use the newer/experimental CSS3 properties. Make sure the fall-back is understandable and then add the features on top for the full-featured rendering.

Further reading

One comment

  1. I think this is a nifty overview of properly cross-platform button styling without requiring all those bothersome little images. Thanks!

Add your comment

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>