building beautiful buttons with css gradients

A special thanks to Ryan Doherty for building this demo and making it easy for me to turn it into a tutorial.

In this demo we’ll walk through a simple use case for the new gradient capabilities coming in Firefox 3.6 (see related article). We’ll build a nice-looking embossed and beveled button using gradients and existing CSS properties. The button in question was developed for the next version of our Personas site.

Using a CSS-based method to generate buttons is a huge upgrade for web site developers. It means you don’t have to regenerate images every time you change text, pages will load much faster because you don’t have to download separate images and it allows text to be easily localized. In this case it also makes the page better from an accessibility standpoint – the text contained in the <a href> can add context.

You can see the final version of this demo, or follow along with the steps outlined here.

Creating the Button

A button is just a rectangular space with a link in it. We can create that with a very simple chunk of HTML:

  
    Get Personas for Firefox
    It's free and installs in seconds
  

This creates a paragraph element and sets a fixed width. The internal “button” is actually a simple <a> link that contains text.

Once we have the width set on the button we need to force the <a> to act like a block element so that the text inside will flow as part of a single element instead of showing up as two distinct parts:

display: block;

We want to choose some nicer fonts and a nicer style:

font-family: Helvetica, Arial, sans-serif;
font-weight: bold;
font-size: 138.5%;

text-align: center;
text-decoration: none;

And add some padding around the text and set rounded corners:

padding: 10px;
-moz-border-radius: 10px;

We set a border around the button and set a background color as a fallback for other browsers. (Except, of course, for IE. See the note below.)

border: 1px solid #659635;
background: #99ca28;

We also want to set the color of the text and add a nice drop shadow to make the text look embossed onto the button:

text-shadow: -1px -1px 2px #777777;
color: #ffffff;

Once we have that we can use the -moz-linear-gradient CSS property to define the gradient so that it has a nice bevel look at the top:

background: -moz-linear-gradient(top, #CFE782 0%,
                                      #9BCB2A 2%,
                                      #5DA331 97%,
                                      #659635 100%);

The syntax here is pretty simple. The “top” means that it starts at the top of the area and heads down to the bottom of the button. The rest of the syntax defines what are called “color stops.” These allow you define gradient transitions that actually transition across more than two colors. This is used in this case because the bevel effect requires a non-linear transition from one color to the next.

In the syntax above, it defines a starting color (0%), an bevel effect (2%), most of the transition (97%) and the border color to finish (100%.) This creates the effect where it’s very light at the top as if there was a light source moving to a darker color near the bottom.

IE Note:

A pithy note about our good friend, Internet Explorer. While older versions of Firefox and Safari both handle the background: -moz-linear-gradient gracefully by not affecting background rendering when they run into a property they don’t know how to handle, IE just shows a white background. One possible work around for this is to include a later background: property for IE in a separate style sheet that’s loaded once this style sheet is loaded. There are probably other ways of handling this, but it’s worth noting that this is an issue.

About Christopher Blizzard

Making the web better, one release at a time.

More articles by Christopher Blizzard…


27 comments

  1. Kamal

    luks kool.. but whn ll it implemented in standard CSS 4 all browsers??

    November 30th, 2009 at 14:34

  2. Rich

    It’s worth having a look at the modernizr library for javascript – it does feature detection for things like this that allow you to apply different styles to elements in browsers that don’t implement the feature.

    It’s worth noting that Webkit also supports gradients, but using different syntax, so you can get this to work in both Gecko and Webkit, meaning it’s really only IE and Opera that get a flat button. To those browsers you could either serve a gradient image (if it’s a big bit of design like a background), or not bother (if it’s a button).

    November 30th, 2009 at 15:07

  3. nemo

    Hey. Thanks for this suggestion.
    Up until now, I’ve always handled arbitrarily long site content by either using a tall background image, or a background image that faded to a solid colour.

    Now, thanks to the writeups on hacks.mozilla.org, I added an extra bit of what I think is prettiness for supporting browsers.
    http://melusine21cent.com/mag/node/42

    This page slowly fades to a dark colour now in Firefox and Safari – I haven’t tested Safari yet.

    Oh. If you look in comments for:
    /mag/themes/melusine/style.css you can see I do have a problem I haven’t figured out.

    I wanted to defined two gradients, to handle the case of no background image in a more attractive fashion. I wanted one gradient to go from a colour representing the top of the current image to the bottom of the current image, and another to continue on past that.
    I tried doing it using a single declaration:
    -moz-linear-gradient(#92dbd6, #077582 1052px, #022228)
    But this resulted in a visible discontinuity. The colour was not precisely matching at 1052px.

    I then tried:
    -moz-linear-gradient(#92dbd6, #077582 1152px), -moz-linear-gradient(#077582 1152px, #022228)

    But this really did not work at all.

    It isn’t a big deal since people usually have that image enabled, but it might be nice to get it working, so I thought I’d ask.

    Oh, and, yes, I had to add an override for IE in the condcom since otherwise it did screw up background-image, choosing to choke on the invalid (from its perspective) line instead of throwing it away.

    November 30th, 2009 at 17:10

  4. nemo

    (one reason it would be nice to get it working is the jpeg is rather large and a smooth gradient would look nicer while loading)

    November 30th, 2009 at 17:12

  5. Neil Rashbrook

    When you’re setting the background colour, why not use the background-color property?

    December 1st, 2009 at 03:33

  6. Goulven

    An inset box-shadow also works for simple bevels.


    beveled link text

    Using box-shadow, -moz-box-shadow and -webkit-box-shadow, it works in all modern browsers, including Firefox 3.5.

    December 1st, 2009 at 05:45

  7. David Tenser

    Very cool. Is it possible to also get a drop-shadow for the whole button as we use on http://support.mozilla.com/en-US/kb/ (for the search box)?

    December 1st, 2009 at 07:22

  8. Goulven

    The style attribute has been stripped from my previous comment, here’s what it should have contained:

    a href=”#” style=”background: #000;box-shadow: 0 5px 10px #fff inset;-moz-box-shadow: 0 5px 10px #fff inset;-webkit-box-shadow: 0 5px 10px #fff inset;”
    Beveled link text
    /a

    December 1st, 2009 at 11:17

  9. Ryan Doherty

    @David: yes, you can use -moz-box-shadow https://developer.mozilla.org/En/CSS/-moz-box-shadow

    December 3rd, 2009 at 23:22

  10. Jakob K…

    This tutorial is nice!
    The button is beautiful!

    January 17th, 2010 at 10:57

  11. […] Building beautiful buttons with css gradients ✩ Mozilla Hacks – the Web developer blog In this demo we’ll walk through a simple use case for the new gradient capabilities coming in Firefox 3.6 (see related article). We’ll build a nice-looking embossed and beveled button using gradients and existing CSS properties. […]

    January 25th, 2010 at 10:21

  12. Ryan Cowles

    Beautiful! Clean, professional, and all CSS. Thanks for the post!

    May 1st, 2010 at 08:55

  13. Matthias

    It would be possible to use

    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=’#9BCB2A’, endColorstr=’#5DA331′);

    for IE compatibility. It’s not at nice since it won’t have the bevel effect but it’s still better than just a white background!

    May 1st, 2010 at 13:32

  14. […] 원본: http://hacks.mozilla.org/2009/11/building-beautiful-buttons-with-css-gradients/ […]

    June 23rd, 2010 at 20:46

  15. […] Beautiful Buttons with CSS Gradients Using a CSS-based method means you don’t have to regenerate images every time you change text, pages will load much faster and it allows text to be easily localized. In this case it also makes the page better from an accessibility standpoint – the text contained in the <a href> can add context. In this demo you’ll be shown a simple use for the new gradient capabilities and learn how to build a nice-looking embossed and beveled button using gradients and existing CSS properties. […]

    July 1st, 2010 at 08:14

  16. […] Building beautiful buttons with css gradients […]

    April 14th, 2011 at 05:32

  17. […] Building beautiful buttons with css gradients […]

    May 15th, 2011 at 12:34

  18. […] Building beautiful buttons with css gradients […]

    May 20th, 2011 at 10:56

  19. […] Beautiful Buttons With CSS Gradients […]

    July 31st, 2011 at 06:01

  20. […] » 查看教程 HTML+CSSdesign, html+css ← Web移动应用:HTML5,CSS和JavaScript /* */ […]

    August 30th, 2011 at 21:30

  21. […] » 查看教程 […]

    August 31st, 2011 at 21:52

  22. […] 10. Beautiful Buttons with CSS Gradients […]

    September 6th, 2011 at 07:15

  23. […] » View tutorial Designy […]

    September 7th, 2011 at 01:10

  24. Evan

    Demo link is broken, no screenshots in the article. Ugh.

    October 13th, 2011 at 15:16

  25. […] » 查看教程 […]

    December 28th, 2011 at 20:31

  26. […] Building beautiful buttons with css gradients […]

    April 8th, 2012 at 05:53

  27. Carl

    Perfect Chris :)

    Thank you very much for this, currently using on the work website (with one or two minor alterations :)

    September 28th, 2012 at 04:03

Comments are closed for this article.