---
title: Make CSS3 Buttons Like a Boss
teaser: 'Step-by-step instructions for designing great buttons for the web with CSS.

  '
tags: design,css
author: Chad Mazzola
published_on: 2011-01-12
---

High-quality interface elements are a great way to add that extra bit of
refinement to a website. I've been maintaining a [repo of CSS3
buttons](http://ubuwaits.github.com/css3-buttons/) for the past few months and
I'm starting to see them slowly make their way out into the real world. This
tutorial is going to give you a deeper understanding of the design thinking that
goes into making these buttons and show you how to make them from scratch.

For this tutorial, we're going to be building the button that Peter Vidani
recently named [2010 Button of the
Year](http://blog.petervidani.com/post/2688504833/id-like-to-name-apples-download-button).
As you can see, we're aiming for an almost exact reproduction of the image-based
button that appears on the [Apple website](http://www.apple.com/itunes/):

[![''](http://images.thoughtbot.com/ui/css3-buttons/css3-button-1.png)](http://images.thoughtbot.com/ui/css3-buttons/)

### [Take a look at the live button](http://images.thoughtbot.com/ui/css3-buttons/)

### Mind your light sources

When designing buttons and other interface elements, it's important to be
consistent about where the light source on your page is coming from. If you look
at the button we're building, you can see that the light source is coming from
directly overhead. This means there is a slight highlight at the top edge of the
button, the background color goes from lightest at the top to darkest at the
bottom, and there is a slight shadow underneath the button. We'll make sure to
keep the light source consistent as we add the hover and active states later on.

Let's look at the code for the normal state of the button.

First, we use CSS3 background gradients for Mozilla and WebKit, with a solid
color for all other browsers.

```css
button {
  background: #3b88d8;
  background: -moz-linear-gradient(0% 100% 90deg, #377ad0, #52a8e8);
  background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#52a8e8), to(#377ad0));
}
```

Next, we add the border color. Keeping in mind the light source concerns we
mentioned above, the top border is slightly lighter than the bottom edge, with
the left and right edges being somewhere in between these two values.

```css
button {
  border-top: 1px solid #4081af;
  border-right: 1px solid #2e69a3;
  border-bottom: 1px solid #20559a;
  border-left: 1px solid #2e69a3;
}
```

We then add two box shadows: one to create the slight highlight at the top of
the button and another for the drop shadow underneath the bottom.

```css
button {
  -moz-box-shadow: inset 0 1px 0 0 #72b9eb, 0 1px 2px 0 #b3b3b3;
  -webkit-box-shadow: inset 0 1px 0 0 #72b9eb, 0 1px 2px 0 #b3b3b3;
}
```

Finally, the text shadow declaration. Because we want the text to appear
slightly inset into the button, we add a slight shadow at the top of the text.
If we wanted the text to appear raised, our shadow would have gone at the
bottom.

```css
button {
  text-shadow: 0 -1px 1px #3275bc;
}
```

### Next, let's look at the hover state of the button

[![''](http://images.thoughtbot.com/ui/css3-buttons/css3-button-2.png)](http://images.thoughtbot.com/ui/css3-buttons/)

For the hover state, we want to imagine that as we move our mouse over the
button, we cast a slight shadow on it, causing it to get darker. This means that
we need to make the background, border, box shadow and text shadow all a bit
darker. We also want to change the cursor style to what you normally see when
hovering over a link, to reinforce the clickability of the button.

```css
button:hover {
  background: #2a81d7;
  background: -moz-linear-gradient(0% 100% 90deg, #206bcb, #3e9ee5);
  background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#3e9ee5), to(#206bcb));
  border-top: 1px solid #2a73a6;
  border-right: 1px solid #165899;
  border-bottom: 1px solid #07428f;
  border-left: 1px solid #165899;
  -moz-box-shadow: inset 0 1px 0 0 #62b1e9;
  -webkit-box-shadow: inset 0 1px 0 0 #62b1e9;
  cursor: pointer;
  text-shadow: 0 -1px 1px #1d62ab;
}
```

### Now, the active state

[![''](http://images.thoughtbot.com/ui/css3-buttons/css3-button-3.png)](http://images.thoughtbot.com/ui/css3-buttons/)

For the active state, we want to imagine that we're depressing the button into
the page. This means that the button will darken and have a shadow cast over it.
We achieve this affect by adding a darker, larger inset box shadow to the
button, along with making other elements of the button darker.

```css
button:active {
  background: #3282d3;
  border: 1px solid #154c8c;
  border-bottom: 1px solid #0e408e;
  -moz-box-shadow: inset 0 0 6px 3px #1657b5, 0 1px 0 0 #fff;
  -webkit-box-shadow: inset 0 0 6px 3px #1657b5, 0 1px 0 0 #fff;
  text-shadow: 0 -1px 1px #2361a4;
}
```

### Finally, the disabled state

[![''](http://images.thoughtbot.com/ui/css3-buttons/css3-button-4.png)](http://images.thoughtbot.com/ui/css3-buttons/)

You make a disabled button like this:

```html
<button disabled="disabled">Download iTunes</button>
```

We add the disabled style to the normal, hover and active states of the button
to ensure that it appears fully disabled. We also changed the cursor style to
reinforce that no action can be taken. (I tweaked my version a bit to remove the
white bottom border found in the original.)

```css
button[disabled],
button[disabled]:hover,
button[disabled]:active {
  background: #999;
  background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#dadada), to(#f3f3f3));
  border-top: 1px solid #c5c5c5;
  border-right: 1px solid #cecece;
  border-bottom: 1px solid #d9d9d9;
  border-left: 1px solid #cecece;
  color: #8f8f8f;
  box-shadow: none;
  -moz-box-shadow: none;
  -webkit-box-shadow: none;
  cursor: not-allowed;
  text-shadow: 0 -1px 1px #ebebeb;
}
```

### Extra credit

Rounded corners in <abbr title="Cascading Style Sheets">CSS</abbr> can sometimes
look a bit jagged. In WebKit browsers, you can use this line to improve their
appearance:

```css
-webkit-background-clip: padding-box;
```

You'll want to add this line after you declare the background, [as described in
this post](http://tumble.sneak.co.nz/post/928998513/fixing-the-background-bleed).

In Firefox, the `button` element gets a bit of extra height that you can
partially eliminate using this declaration:

```css
button::-moz-focus-inner {
  border: 0;
}
```

In my experience, buttons in Firefox still end up a bit taller than in WebKit
browsers, however.

### And now the caveats

This almost exact reproduction of the Photoshop button is possible in Chrome and
Safari on the Mac, with Firefox being almost there. Chrome on Win/Linux
[currently has a bug](http://code.google.com/p/chromium/issues/detail?id=29427)
that affects buttons that use both rounded corners and an inset box-shadow. [A
fix should be coming
soon](http://twitter.com/#!/paul_irish/status/21739945295085568). As expected,
in Internet Explorer these buttons will fall back to a lesser-styled, but still
functional look.
