CSS3 Buttons with Icons

by Jonathan Longnecker

css3 buttons

During the process of coding a web app we’ve been working on for a client, I decided that was time to go CSS3 with their buttons. After using the accessible CSS button technique for a while, it still felt really complicated and maintaining all those images was a pain if you had different sized buttons throughout your site.

So I started coding them up and realized that all the examples I had run across didn’t have icons! “That’s weird,” I thought. So I tried adding a background image and quickly understood why. In CSS3, the gradient background uses the background-image tag. So throwing an icon kills your gradient background.

Psst…If you’re really impatient you can see the demo here. Otherwise read on…

Now, I know that some browsers support multiple background images, but I needed something a bit more cross-browser. So how do we make this:

<a class="button" href="#">Regular Button</a>

have an icon?

The Basics

Well, let’s start with a simple CSS3 button first, shall we? Here’s some styles to get us a nice looking button that falls back to a squared version in Internet Explorer. Thanks to CSS3 Please! we can even get the background gradient in IE.

a.button {
background-image: -moz-linear-gradient(top, #ffffff, #dbdbdb);
background-image: -webkit-gradient(linear,left top,left bottom,
    color-stop(0, #ffffff),color-stop(1, #dbdbdb));
filter: progid:DXImageTransform.Microsoft.gradient
    (startColorStr='#ffffff', EndColorStr='#dbdbdb');
-ms-filter: "progid:DXImageTransform.Microsoft.gradient
    (startColorStr='#ffffff', EndColorStr='#dbdbdb')";
border: 1px solid #fff;
-moz-box-shadow: 0px 0px 4px rgba(0, 0, 0, 0.4);
-webkit-box-shadow: 0px 0px 4px rgba(0, 0, 0, 0.4);
box-shadow: 0px 0px 4px rgba(0, 0, 0, 0.4);
border-radius: 18px;
-webkit-border-radius: 18px;
-moz-border-radius: 18px;
padding: 5px 15px;
text-decoration: none;
text-shadow: #fff 0 1px 0;
float: left;
margin-right: 15px;
margin-bottom: 15px;
display: block;
color: #597390;
line-height: 24px;
font-size: 20px;
font-weight: bold;

Then we lighten the gradient and change the color on hover:

a.button:hover {
background-image: -moz-linear-gradient(top, #ffffff, #eeeeee);
background-image: -webkit-gradient(linear,left top,left bottom,
    color-stop(0, #ffffff),color-stop(1, #eeeeee));
filter: progid:DXImageTransform.Microsoft.gradient
    (startColorStr='#ffffff', EndColorStr='#eeeeee');
-ms-filter: "progid:DXImageTransform.Microsoft.gradient
    (startColorStr='#ffffff', EndColorStr='#eeeeee')";
color: #000;
display: block;

And finally inverse the gradient and text shadow and move it down one pixel on click.

a.button:active {
background-image: -moz-linear-gradient(top, #dbdbdb, #ffffff);
background-image: -webkit-gradient(linear,left top,left bottom,
    color-stop(0, #dbdbdb),color-stop(1, #ffffff));
filter: progid:DXImageTransform.Microsoft.gradient
    (startColorStr='#dbdbdb', EndColorStr='#ffffff');
-ms-filter: "progid:DXImageTransform.Microsoft.gradient
    (startColorStr='#dbdbdb', EndColorStr='#ffffff')";
text-shadow: 0px -1px 0 rgba(255, 255, 255, 0.5);
margin-top: 1px;

Oh! And don’t forget to add a stroke for Internet Explorer since it won’t render that drop shadow. I’ve put it in an IE-specific stylesheet.

a.button {
border: 1px solid #979797;

Adding the Icon

Back to the icon question. How do we add an icon to this that will work cross-browser? Easy! Just add a span around the text. Sounds familiar, right? Add a class of icon and the name of the icon you want as well.

<a class="button icon chat" href="#"><span>Chat Now!</span></a>

In your CSS use this code for the icon class

a.button.icon {
padding-left: 11px;

a.button.icon span{
padding-left: 36px;
background: url(images/icons.png) no-repeat 0 -4px;

Then grab some icons. I’m using the nice set from Greepit. I’ve been trying to sprite related images like this so I put one together for this example. Sprites can drastically cut down on your http requests, especially in a large web app with lots of icons. Then just position the icon image file depending on the icon you choose:

a.button.icon.chat span {
background-position: 0px -36px;
And that’s pretty much it! You can see other than rounded corners and drop shadows the buttons work great even back to IE6 – though you’ll have to figure out transparent .png issues yourself smile

I’ve put together a simple page with a few examples here (and the code will be formatted without line breaks). Go forth and make kick-awesome buttons!

August 03, 2010

Design, Tutorials


  1. Nice method. Thanks for sharing!

  2. Nice write up.  I’ll have to start using this.

    The way I get around the transparent .png is to have one png and one gif version and code it like this:

    background: url(images/icons.png) no-repeat 0 -4px !important;
    background: url(images/icons.gif) no-repeat 0 -4px;

    Since IE6 ignores !important, it uses the gif while everyone else uses the png.

  3. @Jeff no problem, hope it’s useful!

    @Ryan that’s a pretty cool trick! Though I don’t think IE6 ignores it completely. You’d have to be careful in the implementation. See here: http://tinyurl.com/2arogp2

  4. Is it better to use CSS3’s gradient property or to use actual image?
    I read somewhere that using gradient property itself creates an image internally so it slows down the process. If we use a real image, it will be cached be the browser.

  5. @Ashit, well if you’re building for the future gradients are the way to go. Much easier to maintain. And I’m sure even if the browser is creating the image it’s cached as well and doesn’t count as an http request.

  6. I see. Thanks smile

  7. This is nice, except I’m encountering one problem:
    in Internet Explorer, the cursor fails to become a pointer
    when hovering, unless you’re hovering in the text’s domain.
    Note how this happens in your example page when you begin
    hovering to the left of the icon.

    If that’s the case, I wonder if it isn’t best to use a background image
    for the gradient.

    aslo see: http://stackoverflow.com/questions/6056147/cursorpointer-not-working-on-a-cc3-transitioned-link

  8. @anon I’m not seeing that at all in IE7 or 8. Are you using a different version?

  9. Tested on IE8.  (screenshots sent in a separate email)

  10. Great buttons.  IE9 seems to have an issue with the background.  Looks great on other browsers I’ve tested.

Behold our Amazing Portfolio

Check it Out