Progressive enhancement with CSS3

aka how to make funky web2.0™ buttons from text just using CSS that does not break in older browsers.

IE6, IE7, Safari 2,
Firefox 2, Opera 8

>

IE8
 

>

Opera 9.5
 

>

Firefox 3
 

>

Safari 3
 

>

Firefox 3.1b

Webkit nightly

There will be two types of people viewing this article, roughly 50% of you will be using a modern browser with some CSS3 support like Firefox 3, Firefox 3.1b, Safari 3, Opera 10a or a recent Webkit nightly build and will see the progressive enhancement that is possible through CSS3, just turn off your images and check the results. The other 50% will be using browsers without a great deal of CSS3 support, like Internet Explorer 6 or 7, Firefox 2, Safari 2 or even Opera 9.5 and will wonder why there is a row of almost identical buttons above. If you are in that group and have access to a browser in the first list fire it up and look at this page again or skip down to the very bottom of the page to see the only image used and trust me.

Basic button

>

Nothing fancy here, just a text link within a div with a background colour and border inside another div with a background colour and border. With a third transparent div doing nothing. Works in all browsers with proper CSS1 support. IE6 does not render this a perfectly as other browsers, it loses some of the height on the inner div, and has a larger grey bottom border. As this is a proof of concept I am not going IE6 bug hunting.


<div style="width: 105px; height: 105px; padding:4px; border: 4px #000 solid;background-color: #ccc; position:relative;">
<div style=" height: 50px; width: 50px; padding: 25px; border: 2px #333 solid; background-color: #f90; font-size:120px; font-family: arial; line-height: 50px; text-indent: -5px;"> <a href="#" title="play" style="text-decoration:none; color: #fff; font-weight: bold;">&gt;</a></div>
<div style="position:absolute; top: -40px; left: 5px; height: 90px; width: 100px;"></div>
</div>

Opacity

>

Supported by Firefox 2+, Safari 2+, Opera 9+ & IE8+

opacity: 0.25;

Hack for IE5.5+

filter: alpha(opacity = 25);

I could of used a background colour and opacity to give the translucent effect, I did not for the simple reason that some browser do not support opacity, the result in these browser the extra div with be opaque and visually block the top of the text.

RGBA

>

Supported by Firefox 3+, Safari 3+, Opera 10+ & IE8+

background-color: rgba(255,255,255,0.25);

I preferred to use RGBA over opacity to get the translucent effect on the top of the button, because even though it works in less browsers, browsers that do not understand it, ignore it reverting to the previous colour or default settings. Which in this case is transparent.

Unless you are sure what the colour will be, through either the default settings or set earlier in the CSS, you need to set the colour in a format all browsers understand.

Type Shadow

>

Supported by Firefox 3.1+, Safari 3+, Opera 9.5+

text-shadow: 0 0 2px #000, 0 0 25px #fff;

Text shadow is responsible for the dark outline around the text in the example. Firefox 3 and Safari/Webkit support a single text shadow property. Opera and Firefox 3.1 supports multiple text shadow properties which can lead to interesting effects.

The first value is the vertical displacement (X-axis) of the shadow relative to the text. The second value is the horizontal displacement (Y-axis) relative to the text. The third value is blur radius, 0 is no blur. The larger the value the more the blurring occurs, it turns into a indistinguishing smudge around 20px and disappears around 50px depending on the size of the text being shadowed, The fourth value is colour, you can use RGBA to adjust the opacity of the shadow.

For this example only, I am using two text shadows and I had to make compromises. I really wanted the hard dark edge offered by text-shadow: 0 0 2px #000, for browsers that only support one text-shadow value, such as Firefox 3 & Safari 3. Unfortunately, this mean the second text-shadow: 0 0 75px #fff, , overlays the first. I would of liked to used rgba(255,255,255,0.67) instead of #fff. However, Opera 9.5 does not understand RGBA and was delivering a grey smudge, because it did not understand RGBA and used the previous text-shadow colour.

Border Radius

>

Supported by Firefox 3+, Safari 3+

-moz-border-radius: 100px; -webkit-border-radius: 57px; border-radius: 57px;

Border radius rounds corners, while you can make a circle as long as the block element is a perfect square. You can not make an oval, you can only round corners. So with the maximum possible border radius value the shortest side is a perfect half circle.

For a circle the radius equals half the height + padding + border width. If you provide a value larger than that Safari treats it as a value of 0, leaving you with regular straight border. With a rectangular box, the maximum radius is half the smaller of height or width + padding + border width. Again, if you put a larger value, Safari treat it as 0. Firefox will accept a large border radius value, it will only apply the maximum radius.

You can also apply four different border radius values:

border-radius: 0 50px 20px 50px; -moz-border-radius: 0 50px 20px 50px; -webkit-border-radius: 0 50px 20px 50px;

Will deliver 0px radius top left corner, 50px radius top right corner, 20px radius bottom right corner and 50px radius bottom left corner.

Box Shadow

>

Supported by Firefox 3.1+ & Safari 3+

box-shadow: 3px 5px 12px rgba(102,102,102,0.5); -webkit-box-shadow: 3px 5px 12px rgba(102,102,102,0.5); -moz-box-shadow: 3px 5px 12px rgba(102,102,102,0.5);

Shadow for block elements, exactly the same attributes as text shadow and works the same way. As with text shadow, Safari 3 only supports a single instance of text shadow, while Firefox 3.1+ and the Webkit nightly’s support multiple instances using:

box-shadow: 20px 0px 20px rgba(255,0,0,1), 0px 20px 20px rgba(0,255,0,1);-moz-box-shadow: 20px 0px 20px rgba(255,0,0,1), 0px 20px 20px rgba(0,255,0,1); -webkit-box-shadow: 20px 0px 20px rgba(255,0,0,1), 0px 20px 20px rgba(0,255,0,1);

You need to be aware of a problem with Safari 3 (fixed in the latest webkit) rendering a thin dark line outside of the border (if any, otherwise the element itself) of a block element with box shadow applied. So I choose not apply a box shadow to the translucent upper section, except for this example.

There is also a problem with Google Chrome. If an element has a border-radius and box-shadow, the area revealed the border-radius is rendered as black, not the underlying element if a box shadow is applied to the elemnt with a border-radius. So if your visitors use Chrome you will have to make a choice border-radius or box-shadow.

Transform

>

Supported by Firefox 3.1+ & Webkit nightly

-webkit-transform:translateY(20px) scaleX(0.65) scaleY(0.31); -moz-transform:translateY(20px) scaleX(0.65) scaleY(0.31); -o-transform:translateY(20px) scaleX(0.65) scaleY(0.31); transform:translateY(20px) scaleX(0.65) scaleY(0.31);

To give the attention it deserves I will write another article just on transformation either here or at my blog. It is a very powerful tool for manipulating element with CSS, that needs a detailed explanation. This just demonstrate what can be done for the bleeding edge browsers, which should become mainstream shortly, with Firefox3.1.

The existing transparent circular div is moved down, and scaled down both on the X (horizontal) axis and more on the Y (vertical) axis to form an oval.

Conclusion

I hope you like what you saw and the possibilities of using CSS3 to progressively enhance web pages. You should not use CSS3 just because it is the latest and greatest toy. You should use it to enhance the experience of some of your visitors. At current that varies between 15% for your typical corporate site to well over 50% for sites used by web geeks.

More and more browsers are capable of supporting CSS2.1 & CSS3, IE8 is just around the corner and hopefully IE9 will have CSS3 support. So now is the time to learn and experiment, otherwise you will have a steep learning curve later. A good place to start is CSS3 Info.

A couple of notes, I could of used any unit of measurement for this demo. I used px because it was the easiest to calculate and I did not have to worry about browser rounding errors. Also there is a semi-translucent area extending 45px or so above each button in this demo, which I could of hidden, either with a margin-top or fancy footwork and lots of z-indexes. I choose instead to make it obvious, the disadvantage of using curved block elements. It was an interesting experiment, that I will refine and use later.

those links as seen in firefox3.1beta