I'm now using James Padolsey's solution to this problem typically instead of the following.
Browser sniffing is generally frown upon, but there's a massive gorilla in the room: Internet Explorer. While needing JavaScript workarounds specifically for IE are far rarer than CSS, I still find myself needing to use different code for IE - when animating PNG-24s, for instance. Most of us (at least, those of us using jQuery) have grown accustomed to using jQuery.browser for this purpose - even if we know it's not the best practice.
When browser capabilities or implementations differ, feature detection is vastly preferred to user agent detection. However, as Nicholas Zakas points out, feature detection is not browser detection and like him I am reluctant to say there's never a use-case for browser sniffing.
Because of this, I decided to come up with a method of detecting Internet Explorer as an extension to my preferred method of targeting IE through conditional comments that doesn't actually sniff the user agent string.
So, without beating around the bush, here's the little tiny script:
(function () {
var classes = "|" + document.body.className.split(' ').join('|') + "|";
window.isIE = {
any : classes.indexOf('|ie|') !== -1,
v6 : classes.indexOf('|ie6|') !== -1,
v7 : classes.indexOf('|ie7|') !== -1,
v8 : classes.indexOf('|ie8|') !== -1,
v9 : classes.indexOf('|ie9|') !== -1,
lte7 : classes.indexOf('|lte7|') !== -1,
lte8 : classes.indexOf('|lte8|') !== -1,
lte9 : classes.indexOf('|lte9|') !== -1
};
})();
Placing this script in a script block immediately after the opening body tag, you will have access to a global object called isIE which contains boolean values that can be used to target JavaScript to Internet Explorer when used in conjunction with the aforementioned body class method and a minified version of the script - a whopping 314 bytes.
<!--[if lt IE 7]> <body class="ie ie6 lte9 lte8 lte7"> <![endif]-->
<!--[if IE 7]> <body class="ie ie7 lte9 lte8 lte7"> <![endif]-->
<!--[if IE 8]> <body class="ie ie8 lte9 lte8"> <![endif]-->
<!--[if IE 9]> <body class="ie ie9 lte9"> <![endif]-->
<!--[if gt IE 9]> <body class="ie"> <![endif]-->
<!--[if !IE]><!--> <body> <!--<![endif]-->
<script>
(function(){var a="|"+document.body.className.split(" ").join("|")+"|";window.isIE={any:a.indexOf("|ie|")!==-1,v6:a.indexOf("|ie6|")!==-1,v7:a.indexOf("|ie7|")!==-1,v8:a.indexOf("|ie8|")!==-1,v9:a.indexOf("|ie9|")!==-1,lte7:a.indexOf("|lte7|")!==-1,lte8:a.indexOf("|lte8|")!==-1,lte9:a.indexOf("|lte9|")!==-1}})();
</script>
Following this, you will then be able to do something like the following:
if (isIE.lte7) {
alert("I am Internet Explorer 7 or lower!");
} else {
alert("I am NOT Internet Explorer 7 or lower!");
}
And all without sniffing the user agent string. It's not awesome, but it's mildly less awful.