Using Internet Explorer Conditional Comments with EnhanceJS

April 2020 note: Hi! Just a quick note to say that this post is pretty old, and might contain outdated advice or links. We're keeping it online, but recommend that you check newer posts to see if there's a better approach.

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

Permalink to '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

Permalink to '…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. 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

Permalink to '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

All blog posts