Realistic CSS3 Buttons Redux

A cou­ple of weeks ago I posted Real­is­tic Look­ing CSS3 But­tons, in which I tried to make awesome-looking CSS3 but­tons that required no extra markup. For peo­ple who like more code and less talk, the end of the post has the link to the demo.

As awe­some as they were, they required an explicit width. This meant that they didn’t adapt grace­fully to dif­fer­ent labels—you had to explic­itly set a width on the but­tons that might not fit the actual label prop­erly. This had been nec­es­sary to get the nice inner white bor­der, which I’m now using two instances of inset box-shadow to repli­cate (many CSS3 dec­la­ra­tions allow for mul­ti­ples, such as background-image and box-shadow). I would have pre­ferred to do it with only one dec­la­ra­tion, but box-shadow: 0 0 1px #fff inset; pro­duced too dim of an inner bor­der for my liking.

I also wanted a better-looking but­ton depressed state. I emu­lated the inner shadow typ­i­cal of OS X Leopard-era but­tons with a third inset box-shadow on the :active state, as you can see below. Press­ing the but­tons feels really awe­some if your browser sup­ports CSS Transitions.

States: Nor­mal, Hover, Active (left to right)

Speak­ing of CSS tran­si­tions, they’re now used con­sis­tently on the :hover state, by chang­ing the background-color on hover instead of chang­ing the gra­di­ent (gra­di­ents don’t cur­rently ani­mate in a tran­si­tion). I also did a bit more work to make it cross-browser friendly: I used backup col­ors wher­ever rgba() nota­tion was used, as well as a gradient.png fall­back for browsers inca­pable of CSS gradients.

Here’s a few things I found along the way:

  • Fire­fox 3.7 nightly (which will be FF4 even­tu­ally I think) ren­ders the but­tons the best.
  • WebKit doesn’t actu­ally sup­port inset box-shadow yet in Safari 4 or Mobile Safari. So, they get left behind for now. But WebKit nightly and Chrome have landed sup­port for inset box-shadow.
  • WebKit cur­rently has a fas­ci­nat­ing bug with inset box-shadow and tran­si­tions. Using WebKit nightly or Chrome, try click­ing on the “Wonky Webkit Tran­si­tion” but­ton. The box-shadow starts on the out­side and then snaps to the inside at the end of the transition.
  • Fire­fox does weird things with an :after pseudo-element placed on a but­ton ele­ment. I did some hacky things to work around that at the default size using @-moz-document. Not awe­some or recommended.

With­out fur­ther ado (and I use the phrase only to plead with the peo­ple of the world who say “with­out fur­ther adieu” to STOP DOING IT WRONG), check out the Real­is­tic CSS3 But­tons Redux demo.


  1. Posted May 12, 2010 at 2:05 pm | Permalink

    thank you for this Matt.

  2. Posted February 18, 2011 at 12:27 am | Permalink

    Thanks for the tips, now i’m using it on my project :)

  3. Kwinto
    Posted April 10, 2011 at 7:50 am | Permalink

    Great work! Thanks :)

    background-image: –o-linear-gradient(top, rgba(255,255,255,.75), rgba(255,255,255,0));

    to,, {…} class for Opera 11.10+

  4. Matt
    Posted April 10, 2011 at 4:08 pm | Permalink

    @Kwinto Cheers. As for Opera: yeah, I could do that if I get around to it. I guess some peo­ple use it.