Using Internet Explorer Conditional Comments with EnhanceJS

Posted by Scott on 05/11/2010

Recently we released an open-source script called EnhanceJS that lets you apply progressive enhancement to your projects in a practical way: it tests a browser's capabilities before loading CSS or JavaScript enhancements onto a page, and ensures that it receives a usable experience based on those capabilities.

Though IE versions 6 through 8 pass EnhanceJS's capabilities tests and render most enhancements correctly, they sometimes render CSS or JavaScript in quirky ways. Thankfully, Microsoft provided a relatively unobtrusive way for developers to work around these issues called "conditional comments." We've added a feature to EnhanceJS that provides a way to deliver IE conditional comment-based markup enhancements so sites look and work as expected across all versions of IE.

When we first integrated conditional comment support into EnhanceJS, we used an approach that relied on browser sniffing—the script detected the User Agent string and evaluated to see if it matched IE. But browser sniffing is less than ideal for several reasons: browsers can be spoofed, or configured to report a different User Agent than the one actually employed; it required that we continually update all versions of IE; and it It also made it difficult to support the pseudo-standard IE conditional comment syntax that developers already know. Most importantly, it goes against the very principles of EnhanceJS: testing a browser's capabilities to make informed UI decisions.

This is the key to the new approach: instead of testing for a User Agent, EnhanceJS directly tests the browser's ability to support conditional comments. EnhanceJS creates and injects into the page a conditional comment containing an HTML element, and then attempts to find that element using a standard DOM lookup. If the browser can perceive the HTML element, we know it is a version of IE; otherwise it treats the conditional comment like standard comment tag, ignoring the HTML inside it, as all non-IE browsers do. (Details about the script are posted to a thread on github. Big thanks to Paul Irish and Ben Alman for their help in tightening up the approach).

A brief review of conditional comments

When rendering fixes are needed for IE, you can enclose CSS, JavaScript, or HTML markup in conditional comment tags directed at one or more versions of IE with an "if" statement; IE will then execute the code specified within them, while all other browsers treat them as standard comment tags and ignore them. The "if" statement must reference IE in square brackets as shown below; in this example, the link element will render only in IE:

<!--[if IE]>
  <link rel="stylesheet" type="text/css" href="ie_fixes.css" />
<![endif]-->

Conditional comments can also be targeted to a particular version of IE, or a subset of versions, like those released prior to IE7. We recommend being as specific as possible so that the conditional code applies only to the browsers that require it, and not to current or future versions which don't need the fix. Use lt (less than) or lte (less than or equal to) to specify which version(s), for example, the following conditional comment is read only by versions of IE released before version 7:

<!--[if lt IE 7]>
  <link rel="stylesheet" type="text/css" href="ie_fixes.css" />
<![endif]-->

...and a brief review of using EnhanceJS

EnhanceJS runs as the page loads, and if the browser is capable, it injects enhancements in the form of additional CSS and JavaScript files. If the browser doesn't support JavaScript at all, or if it fails any of the capabilities tests, the page renders with plain, usable HTML when coded correctly. (Read a detailed description of how to use EnhanceJS in your projects.) Quickly, use the following script block to call the enhance function, where you can specify options for the CSS and JavaScript files that should be loaded in capable browsers:

<script type="text/javascript" src="enhance.js"></script>
<script type="text/javascript">
    enhance({
        loadStyles: [
            'css/reset.css',
            'css/enhancements.css'
        ],
        loadScripts: [
            'js/enhancements.js'
        ]
    });
</script>

When referenced this way, EnhanceJS creates a link or script element for each CSS and JavaScript file listed, and injects it into the head of your page with default attributes (i.e., rel="stylesheet" type="text/css"). But what if you'd like to specify the value of a particular attribute, like media="print" for a print-only stylesheet? For these cases, EnhanceJS accepts an alternate syntax (object notation) that allows you to set key/value pairs for attributes. The following code demonstrates how you could load a second CSS file, print.css, and specify that it should have a media attribute with a value of print:

…
loadStyles: [
  'css/enhancements.css',
  { href: 'css/print.css', media: 'print' }
],…

To keep it simple, EnhanceJS uses the same attribute syntax you'd write into the page manually, for example, the href attribute that defines the CSS file's location. This syntax can be used to set any attributes you'd like, such as rel="alternate stylesheet", to link to an alternate stylesheet.

Using conditional comments with EnhanceJS

We created a custom attribute called iecondition to specify files only for particular versions of Internet Explorer. When the browser passes EnhanceJS's capabilities tests, if an iecondition key/value pair is listed in the enhance function with a CSS or JavaScript file reference, the resulting link or script element will be written to the page within conditional comments. For example, to include a stylesheet for all versions of IE prior to version 7:

…
loadStyles: [
  'css/enhancements.css',
  { href: 'css/ie-fixes.css', iecondition: 'lt IE 7' }
],…

EnhanceJS accepts all of the conditions that regular conditional comments support. Keep in mind that when using EnhanceJS, you do not need to add the "if" portion of the condition, just the browser version and any preceding qualifiers, like lte. Possible values you could specify with iecondition include:

  • iecondition: 'lt IE 7' - will load only in versions of Internet Explorer older than 7
  • iecondition: 'lte IE 7' - will load only in versions of Internet Explorer less than or equal to 7
  • iecondition: '6' - will load only in IE 6. This is shorthand for "IE 6", which also works.
  • iecondition: 'all' - will apply to all versions of IE. You can also do this with the keyword "IE".

All standard conditional comment value (operators) are supported; the complete list is documented at Microsoft's developer network site: Syntax of Conditional Comments

600

Comments

Awesome update! I recently bought your book, it’s been very helpful reiterating and introducing new ideas of progressive enhancement to me.

Thanks for the gist link too, I might have to reuse this.

Comment by Luke Morton on 05/12  at  11:41 AM

Thanks, Luke. We’re glad you like this update, and thanks for buying our book (great to hear that you’ve found it helpful)!

Comment by Scott (Filament) on 05/12  at  12:17 PM

Really good article which highlight some very valid points about the new IE feature.

Comment by Seo Berkshire on 07/11  at  12:08 PM

Thanks for really good article. It seems that someone did a great work for all of us. What else I could say? Keep up the good work and don’t be shy :)

Comment by fotowoltaika on 09/05  at  10:19 AM

Great to know that you guys are bringing more and more scripts to help us :D

Comment by Merimbula Accommodation on 11/13  at  04:04 AM