Doing anything relatively complex in CSS while maintaining cross-browser support is the bane of web design. All of the major browsers–Firefox, Safari, Opera, and the various flavors of IE–interpret CSS in their own quirky ways (even Firefox slips on a couple of obscure CSS2 items), and none of them seem to agree on the particulars of their quirks. And since most web designers and developers can’t dictate the browser that their visitors will use–”works best in IE” or “please use Firefox” is so tacky–we need to engage in all sorts of trickery to get things to render passably well in the most common browsers.
This is especially frustrating in the case of Internet Explorer, where the differences between versions can be as great as their differences with other browsers. CSS “hacks” that exploited IE6’s failure to parse certain CSS selectors, for example, fail in IE7: or at least, the hacks fail, but the behaviors those hacks tried to mitigate are still there.
In the project I’m currently working on, I wanted to avoid muddying my CSS files with hard-to-decipher hacks. I want my CSS code to be readable and extensible, and to future-proof my design as much as possible against future browser quirks. Client-side JavaScript browser-sniffing techniques are less than reliable, since they often rely on the same kinds of “what features does this browser support” tricks as CSS hacks. In the past–for example, when working with IBM WebSphere Portal Server–I’ve relied on server-side rendering to deliver different CSS files to different browsers, but I wanted to minimize that, too, since I’m modifying an existing J2EE application that is as platform-agnostic as possible.
Then I discovered a hack that Microsoft built into Internet Explorer: conditional comments.
<!--[if IE 5]>
Welcome to Internet Explorer 5.
<![endif]-->
Now, there are a few things that are fundamentally wrong about conditional comments. The worst thing about them is that they violate the whole idea behind comments: comments should NOT contain executable code. Indeed, a common practice for disabling code in any language I’ve used is to “comment it out”: wrap your code in comments, and it becomes invisible to your compiler/interpreter. Wrapping code in comments and intending that code to execute is simply upside down.
Still, this seems to me a more acceptable hack than the other options. It doesn’t rely on browser bugs that, one would hope, the browser manufacturer will fix at some future point; it doesn’t result in unreadable CSS code; and it’s relatively unobtrusive, requiring only a head-scratching bit of commented code that executes in some browsers. Since it’s built on a “feature” of the browser most likely to cause you grief, this is a reasonable workaround that doesn’t adversely affect people who are able to use more standards-compliant browsers.
In my project, I deliver a full stylesheet to all browsers, and then conditionally include subsets that modify the CSS just for the browsers that misbehave.
For example, here’s an unordered list that is styled differently for IE6, IE7, and all other browsers, by using conditional comments:
If you’re using IE 7, you’ll see a blue background on the list items, and a yellow background on mouse hover; in IE 6, you’ll see the blue background but hovering won’t change the color (because IE 6 doesn’t support the “:hover” pseudo-class on non-anchor elements; more on that later . . .); and in any other browser, you’ll see an orange background with a blue hover. Here’s the code:
<style>
<!--
// all browsers (including IEx) see this CSS
ul.conditional-comments-example {
list-style:none;
color:#fff;
width:20em;
padding:3em;
border:1px dashed gray;
}
ul.conditional-comments-example li {
padding-left:2em;
background-color:#E17C1C;
}
ul.conditional-comments-example li:hover {
background-color:#1E4262;
}
-->
</style>
<!--[if IE 7]>
<style>
<!--
// only IE 7 sees this CSS
ul.conditional-comments-example li {
background-color:#016BAD;
}
ul.conditional-comments-example li:hover {
background-color:#ECE990;
color:#000;
}
-->
</style>
<![endif]-->
<!--[if IE 6]>
<style>
<!--
// only IE 6 sees this CSS
ul.conditional-comments-example li {
background-color:#4289AE;
}
ul.conditional-comments-example li:hover {
background-color:#EEEBD9;
color:#000;
}
-->
</style>
<![endif]-->
This is a trivial example, but useful for illustration purposes. In my own case, I found this approach helped me to fix some positioning problems (Firefox and Safari support “display:table” styles, IE doesn’t) and an annoying “jump” in mouse-over code that’s exhibited in IE.
This technique has some potential, if used sparingly and carefully; it would be nice if we didn’t have to use it, but it’s much cleaner than most of the other solutions I’ve seen.