A List Apart


Illustration by Kevin Cornell

CSS3 Bling in the Real World

All you disco-dancing designers out there (no more anticipation of alliteration) have been loving the new features CSS3 provides for making websites look cool in an easier, less hackish, and more straightforward fashion.

Article Continues Below

Features like CSS3 gradients, drop shadows, rounded corners, animations, and opacity are giving us the promise of less time spent in Photoshop, fewer horribly nested <div>s, more flexibility, and more fun! Not to mention more time down at the pub, excitedly showing your friends your latest cool experiments on your iPad, while sipping on a smooth glass of ale with an intense air of self-satisfaction and smugness. Face it, most of us have enjoyed such a moment!

The new breed of CSS3 shizzle even allows a self-confessed design amateur like myself to produce some fairly tasty looking designs. CSS3 is here, CSS3 is fun, and CSS3 allows us to evolve the look of the web as we go. At least, that’s the theory. But the reality is a bit different:

  • On both desktop and mobile (and other alternative browsing devices) there are rendering engines out there other than Webkit. (Many designers out there forget this, and don’t consider the fact that it isn’t that hard to make the new CSS3 features work in other browsers, too.)
  • Some browsers in use today support a reasonable set of features, while some support none at all.
  • Some of us have real live clients who want their websites to look pretty much identical, even across older browsers.

Ok, I’m probably not saying anything that you don’t know already. But putting our fun experiments aside, what CSS3 stuff can we really start using in a wide variety of production sites, right now, without having to wait 10 years until IE6 finally dies of old age and we have to start learning CSS4?

I won’t cover anything approaching all of the features found in CSS3, as, well, I’d be here until Christmas and miss Coronation Street. For now, I will get down to business and look at some of the basic CSS3 yumminess we all know and love, and how to make it as cross-browser as possible:

  • Linear gradients
  • Drop shadows
  • Opacity
  • Rounded corners
  • Web fonts

A suitable example?

To illustrate my points, I’m going to create a funky little bling box and use it as my playground. Here’s what it looks like in the latest versions of Opera, Firefox, Chrome, and Safari:

Fig. 1: CSS3 example as shown in a browser that fully supports CSS3.

We will make some updates as we go along. You can view the initial bling example running live: feel free to do some testing and updates of your own, as I’m sure you can get it looking tastier than I can.

In this example, I’ve taken a simple HTML5 page with a <section> element containing some content, and blinged up that <section> with some fairly gratuitous CSS. I’ll not walk you through all the code, as you would find that tedious; I will, however, point out a few of the more interesting features.

Web fonts

To start with, I went to Font Squirrel, found a fairly nice looking font, and then used the @font-face generator to create cross-browser code for including my font which will work across pretty much any browser:

@font-face {
  font-family: 'MEgalopolisExtraRegular';
  src: url('megalopolisextra-webfont.eot');
  src: url('megalopolisextra-webfont.eot?#iefix') 
  url('megalopolisextra-webfont.woff') format('woff'),
  url('megalopolisextra-webfont.ttf') format('truetype'),
  font-weight: normal;
  font-style: normal;

Rounded corners

To make my example Web 2.0 compliant, I made sure to give my box at least one rounded corner:

border-radius: 30px 0 0 0;

Text shadows

Next, I included several text shadows on the h1 to give it a rather nice-looking 3D effect:

text-shadow: 0 0 1px #000,
  0 0 1px #aaa,
  0 0 2px #999,
  0 0 3px #888,
  0 0 4px #666,
  0 3px 3px rgba(0,0,0,0.5),
  0 4px 10px rgba(0,0,0,0.5);

I also included a simple text shadow on the paragraph to ensure readability if darker colors are chosen for the background color:

text-shadow: 1px 1px 1px #bbb;

(Note: inspiration for my text shadow effect was taken from the rather masterful Jan Henrik Helmers.)

Box shadows

I also added multiple box shadows, including multiple outer box shadows to give the box a more natural feel with multiple light sources, and an inner box shadow (specified by the inset keyword) to give the box some depth:

-webkit-box-shadow: 5px 5px 20px #000,
  1px 1px 1px #000,
  10px 10px 70px #333,
  inset 10px 10px 20px rgba(0,0,0,0.4);
box-shadow: 5px 5px 20px #000,
  1px 1px 1px #000,
  10px 10px 70px #333,
  inset 10px 10px 20px rgba(0,0,0,0.4);

Note: I’m including the -webkit- prefix version; as of the time of this writing, Safari still needs this for box-shadow support. You should always put the non-prefixed version last when using vendor prefixes, so that when browsers stop using the prefix and support the final version, the non-prefixed version will override any different behavior exhibited by the prefixed versions earlier in the source.

Linear gradients

Linear gradients are currently supported across all of the newest browsers with vendor prefixes. We therefore need to add a few lines to get them working cross browser. For my blingtastic example, I have added a white gradient going diagonally across the box at 60 degrees to give the box a nice bit of texture:

background-image: -ms-linear-gradient(60deg, rgba(255,255,255,0),
  rgba(255,255,255,0.2) 50%, rgba(255,255,255,0));
background-image: -moz-linear-gradient(60deg, rgba(255,255,255,0),
  rgba(255,255,255,0.2) 50%, rgba(255,255,255,0));
background-image: -o-linear-gradient(60deg, rgba(255,255,255,0),
  rgba(255,255,255,0.2) 50%, rgba(255,255,255,0));
background-image: -webkit-linear-gradient(60deg, rgba(255,255,255,0),
  rgba(255,255,255,0.2) 50%, rgba(255,255,255,0));
background-image: linear-gradient(60deg, rgba(255,255,255,0),
  rgba(255,255,255,0.2) 50%, rgba(255,255,255,0));


You’ll notice above that for the linear gradients and inner box shadow I’ve used RGBa colors, e.g., rgba(255,255,255,0.2). I’m not varying the color channels, only the alpha channel, so I’m using just pure white and black with varying transparency. The color you see is actually the background-color shining through from behind. This is a great technique in many ways: browsers that don’t support linear gradients will still show a background colour, which is important for readability, and you can simply vary the background-color value to create different color schemes with the effect maintained:

Fig. 2: The same code, but with background-color: #0000a6;.

Crashing down to reality

Great! The design looks cool, and we can go back down to the pub, to show off our groovy experiments again and perhaps break it up a bit by sniggering as we recount the World of Warcraft jokes in The Big Bang Theory. Right? Well, not really. We have a problem. The design is looking less than great in slightly older browsers, and terrible in really old browsers. What should we do?

To start, in order to get browsers to treat the new HTML5 elements properly, we need to set them to display: block; in our CSS:

hgroup, article, header, footer, section {
  display: block;

Next, to get IE to permit styling of these unrecognized HTML5 elements, we need to create instances of them in the DOM, like so:


Here’s how things are looking in some older browsers:

The example as rendered in Firefox 3.6

Fig. 3: Firefox 3.6 on Windows: most of the features apart from the web fonts and text shadows are missing.

The example as rendered in Safari 4   

Fig. 4: Safari 4 on Windows: again, most of the features apart from the web fonts and text shadows are missing.

The example as rendered in Opera 10.60

Fig. 5: Opera 10.60 on Mac: apart from the gradient, things are pretty good in Opera.

The example as rendered in IE9

Fig. 6: IE 9: most of our design is there, but text-shadow is not supported, and the box shadows look weird.

The example as rendered in IE8

Fig. 7: IE 6–8: pretty much everything is missing, except for the web fonts.

Your choice of testing browsers may vary of course, depending on your target audience and other factors.

Picking up the pieces

I am mainly going to worry about IE here, as most of the other browsers get updated pretty regularly, while IE suffers from “old version lock in” syndrome.

Given that, the most reliable way to fix our cross browser issues is to use JavaScript. Yes, I know: it’s less than ideal to use JavaScript to make up for a lack of CSS support, as some users may have it turned off, and you might also find that your pages suffer significant latency as a result of the extra number crunching. But I tend to think of it this way: if a user is browsing the web with JavaScript turned off, their web experience will be pretty crappy anyway, so the loss of a few visual effects is not going to dramatically affect them. In terms of slowing down your pages, you’ll have to judge this on a case-by-case basis.

If you’re antsy, you can test my updated version of the bling example now; let’s talk about how I got there.

CSS3 pie

The main little helper we’ll look at is CSS3 pie, a JavaScript library that adds support for border-radius, box-shadow, gradients, and RGBa colors to older versions of IE.

Read the CSS3 Pie getting started documentation for instructions on how to use it. The short version is that you download CSS3 pie, unzip it, upload it to your web server, then add the following declaration to all of the CSS rulesets that you want CSS3 Pie to make compatible with IE:

behavior: url(path/to/PIE.htc);

We also need to use a special -pie- prefixed version of the background-image property we are using to apply the CSS3 gradient, and change that particular property to read background, not background-image, as CSS3 Pie doesn’t support the longhand values, just the shorthand. The new addition therefore looks like this:

-pie-background: linear-gradient(60deg, rgba(255,255,255,0),
  rgba(255,255,255,0.2) 50%, rgba(255,255,255,0));


The old IE versions now render the design like this:

Fig. 8: The example as rendered in IE8 with CSS3 pie used to add support for the CSS3 stuff.

Now we’re getting there, but what’s with the background color? The answer I found, after a little bit of digging in the CSS3 Pie docs, is that while CSS3 Pie allows IE to render RGBa colors, it can’t render the alpha value; instead, it renders the RGB channels as fully opaque. We are using transparent white variants for the gradient, so it comes out as white. What we need to do here is change the -pie- prefixed background declaration to use solid, non-transparent colors that IE can read properly.

To work out which colors to use, I rendered my bling example in Opera with the inset box-shadow disabled and used the Opera Dragonfly color picker utility to work out which colors were at the edges and middle of the gradient:

Original valuergba(255,255,255,0) on top of #a600a6rgba(255,255,255,0.2) on top of #a600a6
Updated value#a600a6#b630b6

With that information, we can update the CSS3 pie background line to:

-pie-background: linear-gradient(60deg, #a600a6,#b630b6 50%, #a600a6);

This does take away some of those flexible advantages we talked about earlier in the “Opacity” section, but it now gives us the following output in IE:

Fig. 9: The example as rendered in IE8 with CSS3 pie used and a fix for the gradient.

Much better! So the only things we are missing now are the text-shadows and the inset box-shadow, neither of which CSS3 Pie supports. This is a bit of a pain, but I’m sure you’ll agree that the result is now much nicer in old versions of IE.

Where do we go from here?

I don’t currently have an answer to the inset box-shadow issue; let’s hope CSS3 Pie improves its range of support soon. For text-shadow, there is a library called IE CSS3 that works in a very similar way to CSS3 Pie, and can add limited text-shadow support to IE; I’ve added it into my final example:

Fig. 10: The final example as rendered in IE8 with limited text-shadow support via IE CSS3 library.

As you can see, it only works on simple text shadows, and not multiple text shadows, so take it or leave it. You could also consider faking text shadows using IE filters, but you will be labelled unclean, and they are proprietary functions that can result in an additional performance hit. See Cross browser box shadows for an example of IE filters in action.

Why not just use jQuery?

This is a good question; you could probably achieve cross-browser support of CSS3 elements using a JavaScript library and be done with it. If you’ve got the skills, then go for it, but I’d argue this way is easier. All you need to do here is add some modified CSS and JavaScript links; you don’t need to write a bunch of JavaScript. This makes it more pure, and certainly more accessible to those of us who aren’t much good with script (like me). Think of it as a small stopgap until we don’t need to support those pesky old browsers any more.


I hope you have found this exploration useful. If you have more ideas about making this blingtastic stuff work across browsers, share them in the comments!

About the Author

36 Reader Comments

Load Comments