Creating a Web 2.0 Button with CSS3 and Minimal Markup

The beauty of CSS3 is not just in the fancy effects, but also in the numerous ways it provides for styling your semantic, up to the point and concise markup. The solution below demonstrates how to create a imageless navigation bar with CSS3 gradients and shadows, and even apply icons by using generated content via the :before pseudo element. Here‘s the final and crossbroser (with fallbacks for older browsers) result:

… Produced by the following markup:

<ul>
<li><a href=”#” title=”RSS”>RSS</a></li>
<li><a href=”#” title=”Blogger”>Blogger</a></li>
<li><a href=”#” title=”MSN”>MSN</a></li>
</ul>

… And the CSS explained in brief (on the demo page you can view the complete stylesheet or download the example):

1. The normal state of the buttons:

ul.menu a
{
 -moz-border-radius: 9px;
 -webkit-border-radius: 9px;
 border-radius: 9px;
 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#65a5ed", endColorstr="#aeeaff"); /* Internet Explorer */
 background: #65a5ed; /* Opera and really old browsers */
 background: -moz-linear-gradient(
        center bottom,
        rgb(150,238,255) 11%,
        rgb(131,178,229) 41%,
        rgb(85,155,229) 54%,
        rgb(194,204,234) 94%
    ); /* FireFox 3.x */
 background: -webkit-gradient(
        linear,
        left bottom,
        left top,
        color-stop(0.11, rgb(150,238,255)),
        color-stop(0.41, rgb(131,178,229)),
        color-stop(0.54, rgb(85,155,229)),
        color-stop(0.94, rgb(194,204,234))
    ); /* Chrome and Safari */
 background: linear-gradient(top, #65a5ed, #aeeaff); /* Support for W3C CSS gradients */
 -moz-box-shadow: 0 0 4px #000; /* FireFox */
 -webkit-box-shadow: 0 0 4px #000; /* Chrome and Safari */
 box-shadow: 0 0 4px #000; /* FireFox, Chrome, Safari, Opera, IE9 */
 }

Since no browser supports the official W3C background gradient properties yet, we define them separately for each browser, making sure that we put a fallback alternative for browsers that do not support gradients before all other gradient properties. Our solution will support gradients for IE5.5-9, Mozilla FireFox 3x, Apple Safari and Google Chrome. Opera will display a solid color background, as it still does not support CSS3 gradients.

2. For the :hover state we just change the properties we need to look different:

ul.menu a:hover
{
border-color: #000062;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=”#dbdbdb”, endColorstr=”#ffffff”);
background: #dcdcdc;
background: -moz-linear-gradient(
center bottom,
rgb(255,255,255) 0%,
rgb(214,214,214) 50%,
rgb(235,235,235) 71%,
rgb(248,248,248) 85%
);
background: -webkit-gradient(
linear,
left bottom,
left top,
color-stop(0, rgb(255,255,255)),
color-stop(0.5, rgb(214,214,214)),
color-stop(0.71, rgb(235,235,235)),
color-stop(0.85, rgb(248,248,248))
);
background: linear-gradient(top, #dbdbdb, #fff);
-moz-box-shadow: 0 0 6px #000;
-webkit-box-shadow: 0 0 6px #000;
box-shadow: 0 0 6px #000;
}

3. The :active state is even skinnier:

ul.menu a:active
{
-moz-box-shadow: 0 0 2px #000;
-webkit-box-shadow: 0 0 2px #000;
box-shadow: 0 0 2px #000;
}

And now the most interesting part. CSS3 supports multiple backgrounds on a single element, but still no browser provides means to inherit certain common properties from a parent element, so in order to apply icons we should use the :before pseudo element instead of definining multiple backgrounds (the gradient plus the icon) separately for each button:

1. Create a common :before rule that will be the same for all buttons in the menu:

ul.menu a:before
{
 content: "";
 margin: 4px;
 display: inline-block;
 height: 24px;
 width: 24px;
 background-repeat: no-repeat;
 background-position: center;
 float: left;
}

The above instructs the browser to render a pseudo element before the actual content of the element with the properties we define. Now we have a square 24 x 24 pixels inline-block element, which can accept a background image (the icon). To have a different icon for each button we apply classes to out <a>…</a> tags and then use this simple rule for each button:

ul.menu a.rss:before
{
 background-image: url("pages/creating-a-web-2-0-button-with-css3-and-minimal-markup/images/rss.png");
}
ul.menu a.blogger:before
{
 background-image: url("pages/creating-a-web-2-0-button-with-css3-and-minimal-markup/images/blogger.png");
}
ul.menu a.msn:before
{
 background-image: url("pages/creating-a-web-2-0-button-with-css3-and-minimal-markup/images/msn.png");
}

To optimize even more out menu we can use a single sprite for all icons in the menu or embed the images directly in the stylesheet as bas64 encoded data.

On this page you can see a working demo of the example and you can download it in case you need it. The example works with FireFox, Chrome, Safari, Internet Explorer and Opera. Internet Explorer 5.5 6 and 7 will not display the icons, because these browsers do not support generated CSS content, but still the gradients will work. Internet Explorer will not render the shadows and the rounded corners, but IE9 will.

Find more experiments here.

About these ads

18 comments

  1. Excellent trick, I was styling a few tabs last week for a client and wasn’t very happy having to add needless mark-up in order to achieve the icons (I just hate this). I so need to go back and improve it now.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s