Supporting IE with conditional comments
Introduction
Nearly three years ago, as the IE development team called for developers to clean up their CSS hacks in preparation for the release of IE7, I wrote a blog post called Future-proof your CSS with Conditional Comments, which detailed how to use a proprietary Microsoft technique to avoid CSS hacks by feeding separate CSS (or JavaScript, or whatever) to different versions of Internet Explorer.
It led to a stranger at a conference thanking me for saving his professional life and sparked a good debate, in which I was either a jobbing pragmatist or an incarnation of Satan, depending on your view. (Actually, I’m both. Bwa-hah-hah!)
Three years is a long time on the Web. Back then, IE7 was yet to come, its precursors IE6 and IE5 were hanging in the air like a bad smell in an unventilated bathroom, and more and more elaborate CSS hacks were being discovered and used. Some style sheets were so full of weird backslashes, stars, and underscores that they looked more like a regular expression or Perl. I recommended the removal of such hacks and using Microsoft’s conditional comments instead.
Now, midway through 2008, I’m not so quick to recommend conditional comments. There are fewer reasons to hack; the browser landscape has changed and settled down into one that generally is quite standards friendly (although the bathroom doesn’t quite smell of roses yet), and, with IE8 on the horizon, there are fewer and fewer users of the dinosaur browsers.
Nevertheless, many people do still use conditional comments—many because of my original article—so I’m republishing the 2008 remixed article. Caveat emptor.
Below you’ll learn:
- What CSS hacks do and the issues with them
- How to use conditional comments and why they aren’t perfect either
- What to do to make sure the different versions of IE still in widespread use won’t spit out their dummies when presented with your Web site to parse.
What CSS hacks do
CSS hacks allow Web developers to send different rules to different browsers, usually (paradoxically) to make each browser’s rendering of the site look the same. This is generally necessary as Internet Explorer 5 and 6 have many bugs, so they can get “good” rules wrong.
There are two types of CSS hacks:
- “Parsing Error Hacks” use the fact that browser “x” stops reading a rule when it sees some weird combination of characters, while browser “y” continues unvanquished and receives the subsequent good rules. The problem with these is that they’re utterly unintuitive because they’re pretty random. If they aren’t well commented, you’ll never guess what they do.
- “Weak CSS Support Hacks” use the fact that IE<7 can’t support advanced CSS selectors, and use those to feed a rule to more advanced browsers, usually to override a rule sent to the old IEs.
There are now a gazillion documented CSS hacks, but one of the most common CSS hacks is a box model hack to get over the broken box model in IE5. There are several, but all rely on parsing errors.
Most of the magic behind Parsing Error Hacks involves fooling different browsers into seeing the hack or not. For example, all the voice family nonsense is merely fooling IE5 not to read any more of the rule, so as to not overwrite its overly wide dimensions:
#sidebar { margin:0; padding: 0 15px; width: 194px; /*IE 5.5 width - Tantek hack */ voice-family: ""}""; voice-family:inherit; width: 164px; /*real width*/ }
The “Simplified Box Model Hack” uses a different IE parsing error:
#sidebar { border: 10px; padding: 10px solid; width: 100px; /* real width for proper browsers */ } /* only IE<7 gets rules beginning with * html */ * html div { width: 140px; /* IE5 width */ w\idth: 100px; /* IE6 width (IE5 chokes on backslash character so doesn't over-write the rule again */ }
Given that all this is to overcome deficiencies in Internet Explorer, you might be thinking that it would be superlovelygorgeous if we could have a good, valid, hackless style sheet and an extra one flagged as “Hey! IE6! this is for you!”. Well, we can, using conditional comments.
How conditional comments work
These are plain HTML comments, with a marker so that IE parses them and you can use them to enclose any HTML code—including the linking of a style sheet. They were introduced in IE5 for Windows, so they can’t be used to target previous versions of IE (but if you’re concerned about IE4, dude, you have problems). The best thing is that, because these are HTML comments, they’re invisible to all other browsers, and they pass validation.
Here’s the syntax I use to feed rules to IE5:
<link rel="stylesheet" href="styles.css" type="text/css" /> <!--[if lt IE 6]> <link rel="stylesheet" href="boxmodel.css" type="text/css" /> <![endif]-->
The main styles.css has this simple rule:
#sidebar { margin:0; padding: 0 15px; width: 164px; } /*see boxmodel.css for IE5 override */
The boxmodel.css—which is only served to IE5—overrides it thus:
#sidebar {width: 194px;} /*other rules in styles.css */
No confusing voice-family
hacks or weird escape characters. Huzzah!
IEbugs.css—correcting the main bugs and IE6 and earlier
A lot of CSS hacks feed rules to IE6 and below to compensate for the lack of many important features of modern Web development, like PNG alpha transparency, CSS min-height
and fixed positioning.
You can remove the hacks by calling a special override style sheet called IEbugs.css for IE6 browsers or below, like this:
<!--[if lte IE 6]> <link rel="stylesheet" href="IEbugs.css" type="text/css" /> <![endif]-->
The operator lte
is Microsoftian for "less than or equal to".
Simulating min-height
Suppose you have a box that should never be less than 100px tall—perhaps you have a 95px background image that you always want displayed, but you can’t predict the quantity of content. In a standards-compliant browser, you’d use min-height
, but this doesn’t work in versions of IE less than IE7.
To work around it, you can add a rule specifying the height (which works the same as min-height
should). So, if the rule in the main style sheet says #box {min-height:100px;}
, it should be supplemented in IEbugs.css by:
#box { height:100px; overflow:visible; } /*simulate min-height */
Give GIFs to IE, PNGs to the good guys
People who are more design-oriented than I am have long used graphics in the PNG format for their layouts, as it allows them much more flexibility and loveliness. Unfortunately, IE6 doesn’t do PNGs properly, so people have used another hack to send an alternative image that’s a GIF to IE. Here’s an example, using the * html
hack that only IE understands:
#lovely { background: url(lovely.png) no-repeat; } * html #lovely { background: url(lovely.gif) no-repeat; }
IE7 can do PNGs properly, and it does not understand the * html
rule, so it receives the PNG sent by the first rule: all well and good. But as this is a rule for pre-IE7 browsers, it would be better sent to the doghouse of IEbugs.css.
Once banished, it won’t need the * html prefix, as the style sheet is only being sent to IE<7, and will overwrite the main rule. So, the main style sheet keeps #lovely {background: url(lovely.png)no-repeat;}
, and IEbugs.css adds #lovely {background: url(lovely.gif) no-repeat;}
.
Stopping long words destroying layout
Contrary to the spec, IE allows very long words to expand a box widthwards—which can then easily destroy a layout if other boxes are floated right. This is particularly dangerous in areas where content can’t be rigidly controlled and tested, such as where blog comments are displayed, as someone can accidentally (or maliciously!) enter a very long word and totally nuke your design.
There’s a CSS 3 property that will fix this which IE respects (because it was originally a Microsoft invention that was later added to the spec).
As it’s only IE that will actually wreck the layouts because it allows boxes to expand to fit content, you can add this rule to the box that holds blog comments (or do what I did, and just add it to the body
element):
body {word-wrap: break-word;}
Advanced IE6 bugfixing and hasLayout
If your design requires the ability to hover over any element, rather than just the a
element as IE6 restricts you to, you can add the CSS hover behavior in the IEbugs stylesheet:
body {behavior:url("csshover.htc"); }
You can even go the whole hog and simulate IE7 with Dean Edwards’ JavaScript library, which uses conditional comments to pull in a JavaScript library.
IE.css—serving styles to all versions of IE
Another good use for conditional comments is to separate IE-only extensions to the CSS spec, as they’ll stop your main styles.css from validating (and aren’t necessary in a non-IE browser, so why send them?).
Such extensions would be filters on images, or colored scrollbars.
Here’s the code for the head
of the page:
<!--[if IE]> <link rel="stylesheet" href="IE.css" type="text/css" /> <![endif]-->
If you don’t need these extensions, or you don’t care that you have stuff in your main style sheet that won’t validate (and, in a practical world, there are absolutely no negative side-effects if you have, but it can be very useful for testing and QA if you do validate) you can just leave this in the main style sheet.
Another potential use for an IE.css is to add IE Layout to certain elements, which can help stop many IE rendering bugs. For example, adding a background image to the bottom right of a link in IE7 (if you want to add an icon depending on file type) can break if the link wraps over the end of a line—which is impossible to predict or prevent. The cure (setting the proprietary property zoom:1
) can be added to an IE-only style sheet—for example:
a[href*=".ppt"], a[href*=".pdf"], a[href*=".doc"], a[href*=".xls"] { background: url(icon-download.gif) no-repeat center right; padding-right: 17px ; zoom:1; }
IE/Mac: the new Netscape 4
If you need to feed rules to IE/Mac (which is as obsolete as Netscape 4), there are hacks available, but you should consider importing a separate IE/Mac style sheet in your HTML header and keeping all IE/Mac rules in there:
<style type="text/css"> @import("IEMac.css"); </style>
The formatting of the import must be exactly as above. (Hat-tip.) Alternatively, you can keep your HTML header clean and import a separate IE/Mac set of rules from your main style sheet via Tantek’s IE5/Mac Band Pass Filter, which is made out of fairy dust:
/*\*//*/ @import "ie5mac.css"; /**/
Get yer code on, baby
To recap, here’s all the code for your header (though you probably won’t need all of it):
<link rel="stylesheet" href="styles.css" type="text/css" /> <!--[if IE]> <link rel="stylesheet" href="IE.css" type="text/css" /> <![endif]--> <!--[if lte IE 6]> <link rel="stylesheet" href="IEbugs.css" type="text/css" /> <![endif]--> <!--[if lt IE 6]> <link rel="stylesheet" href="boxmodel.css" type="text/css" /> <![endif]--> <style type="text/css"> @import("IEMac.css"); </style>
Minimizing HTTP requests
Each style sheet pulled in requires an extra HTTP request, which can slow things down, because the HTTP gnomes get tired easily. In order to minimize these, you can combine all IE-facing hacks into a single IE.css, although you still need a version of the box model hack in here so IE5 gets the wider box.
To send 164px width to IE6, and 194px width to IE5 use this code:
#sidebar {width: 194px; /*IE 5.5 width - Tantek hack */ voice-family: ""}""; voice-family:inherit; width: 164px; /*real width*/ }
Testing
Traditionally, and frustratingly, it’s been impossible to install more than one version of IE on a Windows operating system, making testing difficult. If you’re running Windows XP, you will weep with gratitude when you download the multiple IE installer that installs IE3(!), IE4, IE5, IE5.5, and IE6 with version numbers in the title bar and respects conditional comments. If you're running Vista, you’re out of luck.
Using conditional comments to hide something from IE/ Win
It’s also possible to hide HTML from IE/Win:
<!--[if !IE]>--> do something; IE will ignore this, other browsers parse it <!--<![endif]-->
This validates fine. (Hat-tip Lachlan Hunt via Roger Johansson.)
Summary
Conditional comments are simple to use and effective in sending out special rules to the dinosaur browsers. They have their good points and negatives, however. For the prosecution:
- They are contrary to the specification ("Information that appears between comments has no special meaning"), but this is a very purist objection, as they validate perfectly.
- They are a form of browser-sniffing, albeit one that you can guarantee will be future proof.
- They separate out the styles into several sheets, which could lead to maintenance hell.
- They are incompatible with the "vision" of CSS as a cross-platform, open standard.
- They give Microsoft an excuse not to tidy up their browsers.
In defense of conditional comments:
- They allow you to ensure that your site works in standards-compliant browsers like Opera, and then add hacks for the bad browsers without worrying about regression testing (because you know that your IE5-facing rules won’t have some unintended side-effect in Camino or Flock or whatever).
- They allow you to put your invalid, IE-only properties (
zoom
,scollbar
), etc. in a separate style sheet, preserving the validity of the rest of your CSS. - They allow you to ghetto your IE-only rules and to reduce the regex-like hacks that are difficult to understand and may have unintended consequences in future browsers.
Further reading
- Why Conditional Comments Are Bad, Repeat: Bad—Jens Meiert
- Pandora's Box (Model) of CSS Hacks And Other Good Intentions—Tantek Çelik
- About Conditional Comments—Microsoft Developer's Network (check out the first 2 sentences for some oh-so-1998 ideas).
This article is licensed under a Creative Commons Attribution, Non Commercial - Share Alike 2.5 license.
Comments
The forum archive of this article is still available on My Opera.