Opacity used to be the domain of flat images made to look transparent. Then came along 24-bit PNGs with their alpha layer and things were a lot better. Now there are several options for opacity:
- Transparent PNGs
- The opacity CSS property
- RGBA color
Transparent PNGs
Transparent PNGs are probably the most used of the lot because they're the most consistent. There are were two downfalls: IE6 incompatibility and image size. Image size is still a problem, but IE6 no longer gives me any problems. How's that I no longer worry so much about IE6? The DD_belatedPNG library.
It's simple enough to use: include it in an IE6 conditional comment and pass the function the CSS selectors of the elements that have the transparent PNG backgrounds.
1 2 3 4 5 6 7 | <!--[if lte IE 6]> <link rel="stylesheet" href="/css/ie6-only.css" type="text/css" media="screen" charset="utf-8" /> <script src="/js/belatedPNG.min.js" type="text/javascript" charset="utf-8"></script> <script type="text/javascript" charset="utf-8"> DD_belatedPNG.fix('#header h1 a, #wrapper, #home #feature img, #feature'); </script> <![endif]--> |
Did I mention that this works with repeating background and positioned backgrounds? With the addition of this library I no longer worry so much about transparent PNGs and compatibility, I just go for it.
CSS opacity
This is probably my least favorite of the three for one big reason: everything within the element now has the same opacity. Here's an example:
1 2 3 | <div id="container"> <p>Some text belongs <a href="#">here</a>.</p> </div> |
If you apply an opacity to #container of 0.6, the paragraph will also have an opacity of 0.6. You can easily get around it by setting the opacity of the container back to 1.0, but it seems like a bit of a hassle when you consider what you have to do for IE:
1 2 3 4 5 6 7 8 9 10 11 | #container { opacity: 0.6; -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=60)"; filter: alpha(opacity=60); } #container p { opacity: 1.0; -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; filter: alpha(opacity=100); } |
I know I'd prefer something other then this. That's where the RGBA colors come in.
RGBA Colors
I have been waiting for something like this for a while, and once I can reliably combine this with border-radius properties we are all set. RGBA colors allow us to set an opacity on any color on anything: text, backgrounds and borders. The problem with them is that IE7 and IE6 don't support them, but progressive enhancement is your friend so apply it here as well.
Another small problem with RGBA colors is getting your head around the format if you are used to hex colors. When declared an RGBA color looks like this: rgba(255, 255, 255, 0.7). The first number represents your red channel, the second is the green, the third is the blue and the fourth is the alpha channel. Red, green and blue range from 0 to 255. The alpha channel ranges from 0.0 to 1.0.
I used this in two places in a recent project: links and a large border. There was a 6 pixel border sitting under a header in the feature area of a home page that was transparent and white. The links were my idea. When the links aren't being hovered they display as a somewhat transparent white. When you hover over them they turn to an opaque white.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #feature h2 { color: #ffffff; font-size: 2.8em; line-height: 1.3em; margin: 0.9em 0 0.7em; padding: 0 0 0.55em 0; border-bottom: 6px solid rgba(255, 255, 255, 0.3); } #feature li a:link, #feature li a:visited { color: rgba(255, 255, 255, 0.8); text-decoration: none; } #feature li a:hover { color: rgba(255, 255, 255, 1.0); text-decoration: underline; } |
Which gives us two great effects: our border shows any color variations or images below it and our links have a subtle change from somewhat to transparent to completely opaque that reinforces the hover quite well. We already know that this great effect doesn't work in IE7 or IE6, but what happens when this CSS is served up to IE? Well sadly, it doesn't fail gracefully, it completely ignores the rgba and moves on. I combatted this in two ways:
- For the links I added a hex color property after the rgba color and set the rgba color as !important.
- For the border, I declared a hex color border property before the rgba border.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #feature h2 { border-bottom: 6px solid #63b0d5; border-bottom: 6px solid rgba(255, 255, 255, 0.3); } #feature li a:link, #feature li a:visited { color: rgba(255, 255, 255, 0.8) !important; color: #f6e2e5; } #feature li a:hover { color: rgba(255, 255, 255, 1.0) !important; color: #ffffff; } |
It seems to me that this is ready to be used pretty wide-scale. While not everyone is going to get the same exact experience, is that such a bad thing? As developers, we want to discourage people from using non-standards compliant browsers and giving everyone the same experience is not going to discourage anyone. This seems like a good start.
This is how I do opacity, but how do you do it?
I agree Wes. Reward the better-browser-users with a better experience. Makes sense.
Posted by Ryan Huber on 01/14/09 at 6:57AM