If you’re using HTML5 elements then you’re probably also using a JavaScript shiv to help make it possible to style those elements in versions of Internet Explorer prior to IE9. But when JavaScript is disabled the accessibility of the content may be affected in these versions of IE. This is one way to provide a more accessible fallback.

The concept is to ensure that all modern browsers are served the default style sheet(s) and that people using older versions of IE only download them if JavaScript is enabled. When JavaScript is not enabled, people using those browsers can be served either no styles at all (as Yahoo! suggests for browsers receiving C-Grade support) or simple fallback styles.

Client-side method: conditional comments

Doing this on the client-side comes at the cost of having to litter your code with proprietary conditional comments. First, it’s necessary to comment out the default style sheet(s) from versions of IE earlier than IE9. All other browsers will be able to read the file(s).

<!--[if ! lt IE 9]><!-->
<link rel="stylesheet" href="/css/default.css">
<!--<![endif]-->

For earlier versions of IE, an HTML5 shiv is included and the necessary link elements are created and added to the DOM using JavaScript. This means that when JavaScript is not enabled in IE7 or IE8 the style sheet will not be present, resulting in an unstyled HTML page. In this example, IE6 won’t be served CSS at all.

<!--[if (IE 7)|(IE 8)]>
<script src="/js/html5.js"></script>
<script>
(function() {
var link = document.createElement("link");
link.rel = "stylesheet";
link.href = "/css/default.css";
document.getElementsByTagName("head")[0].appendChild(link);
}());
</script>
<![endif]-->

To support multiple style sheets, an array and for loop can be used.

<!--[if (IE 7)|(IE 8)]>
<script src="/js/html5.js"></script>
<script>
(function() {
var css = [
'/css/default.css',
'/css/section.css',
'/css/custom.css'
];
var i;
var link = document.createElement('link');
var head = document.getElementsByTagName('head')[0];
var tmp;

link.rel = 'stylesheet';

for(i = 0; i < css.length; i++){
tmp = link.cloneNode(true);
tmp.href = css[i];
head.appendChild(tmp);
}
}());
</script>
<![endif]-->

Thanks to Remy Sharp and Mathias Bynens for helping me to improve this script. Fork it.

Rather than serving unstyled content, it may be preferable to provide some simple fallback styles. This can be done by linking to a separate style sheet wrapped in noscript tags. In this example, IE6 will always use these legacy styles while IE7 and IE8 will do so only when JavaScript is disabled.

<!--[if lt IE 9]>
<noscript>
<link rel="stylesheet" href="/css/legacy.css">
</noscript>
<![endif]-->

You may wish to use a generic style sheet, such as “Universal IE6 CSS”, or spend a few minutes crafting your own and ensuring that the typography and colours approximate those in the default style sheet.

The complete example code is as follows:

<!--[if ! lt IE 9]><!-->
<link rel="stylesheet" href="/css/default.css">
<!--<![endif]-->

<!--[if (IE 7)|(IE 8)]>
<script src="/js/html5.js"></script>
<script>
(function() {
var link = document.createElement("link");
link.rel = "stylesheet";
link.href = "/css/default.css";
document.getElementsByTagName("head")[0].appendChild(link);
}());
</script>
<![endif]-->


<!--[if lt IE 9]>
<noscript>
<link rel="stylesheet" href="/css/legacy.css">
</noscript>
<![endif]-->

Server-side method: user-agent string detection

The drawbacks of current client-side approaches to IE fallbacks is that they are IE-specific, make extensive use of conditional comments, and have to use JavaScript to create or rewrite link elements. This blog makes use of an alternative approach: server-side user-agent detection. It was inspired by Yahoo!'s Graded Browser Support strategy – created by Nate Koechley – which recommends that all CSS and JavaScript is withheld from legacy browsers (not limited to IE).

The source code in the head of this blog changes when viewed in modern browsers, IE8, and legacy browsers that are incapable of styling HTML5 elements (e.g. Firefox 2) or lack adequate CSS2.1 support (e.g. IE7).

Browsers are assumed to be capable; there is no need to update the script every time a new browser is released. Only when a browser is deemed to be severely incapable is it added to a “blacklist” and served simple styles to ensure that the accessibility of the content is maintained. This is the method I prefer, although it does require more time upfront.