Feature sniffing Internet Explorer

Pretty much all web developers should know by now that browser sniffing is evil. If you don’t know why, you should definitely read Richard Cornford’s excellent treatise¬†Browser Detection (and What to Do Instead). Feature detection, where you look for the specific feature you want to use, is much safer; taken to the extreme, it can end up like the rather clever Modernizr project. But what if you really do just want to know if your code has the misfortune to be running on IE7?

Ideally, you should use Microsoft’s conditional comments to handle that, for example here’s how to load a script segment specifically for IE7:

<!--[if IE 7]>
<script src="fix-ie7.js"></script>
<![endif]-->

But what about handling browser differences deep in the middle of a big script? What if feature detection tells you that a feature is there, but can’t tell you that it’s broken on that browser? It would be nice to be able to work out what browser you’re on, and handle the fix, all from JavaScript.

Of course, you could always resort to the evil browser sniffing, looking at the user agent to see what you’re running on, but that way is fraught with peril as discussed at length by Cornford and others. In fact some pretty popular scripting tools out there do just that, including jQuery and TinyMCE just to name a couple… even though jQuery itself warns about using browser sniffing!

But there is another way. By using some knowledge about which browsers support which features, specifically non-standard features that should never be implemented by other browsers, you can infer which browser you are running on. Feature detection is still the better way to determine which path your code should take, but if you really want to nail down which browser you’re on then it can help you do that too. (And this isn’t a new idea either; check this page for some other examples)

Most likely, if you want to know which browser you’re on, you want to know whether it’s Internet Explorer or not, and maybe which version. Fortunately, Microsoft was a great innovator in web browsers once, and equally fortunately the rest of the browser world decided not to follow their lead on some things, or adapted them in ways that lead to different object names. That means we can easily test for Internet Explorer and the different versions often seen in the wild today.

Here’s a table of some browser properties you can check for. Note that you need to check the first one, to determine that you’re on Internet Explorer, before checking the others; this is because some other browsers do/don’t implement features also. For example, some older browsers don’t have the maxHeight style property, but that doesn’t mean you’ve got IE6 unless you can also find the filters collection.

[edit: changed IE test because IE10 doesn’t have filters collection, but does have documentMode]

browsersniff
IE"documentElement" in document && ("filters" in document.documentElement || "documentMode" in document)
IE6!("maxHeight" in document.documentElement.style)
IE7"maxHeight" in document.documentElement.style && !("documentMode" in document)
IE8+"documentMode" in document
IE9+"performance" in window
IE10+"history" in window && "pushState" in window.history
IE11+"ActiveXObject" in window && !window.ActiveXObject
Edge+"msCapsLockWarningOff" in window && !("documentMode" in document)

An interesting point about the IE8+ sniffs: they tell you which version you’re running on, regardless of the document mode that has been selected. This means that you can use them whether that silly incompatible button has been clicked or not. If you need to know what compatibility mode you’re running too, check the documentMode property.

What about other browsers? OK, here’s a couple of other features you can check for. These may change as the browsers evolve, but they are reliable today. Of course, that’s why feature detection, not browser detection, is better! But there’s no harm in it if you’re just patching up problems here and there.

[edit: I used to have MozOpacity below to test for Mozilla, but recent builds no longer have that property, so I have updated it to MozAppearance]

browsersniff
Opera"opera" in window
Chrome"chrome" in window
Mozilla"MozAppearance" in document.documentElement.style
Webkit"webkitAppearance" in document.documentElement.style

And here’s a sample page showing these tricks in action, alongside browser sniffing. Please let me know if you find something that breaks this.

Facebooktwittergoogle_plusredditlinkedinmailFacebooktwittergoogle_plusredditlinkedinmail