Why is browser sniffing not a recommended practice?

You hear it all over the place: using javascript to sniff the user agent string to detect browser versions is a Very Bad Thing. The latest version of jQuery has now deprecated its $.browser object in place of $.support. But what should I do if there's a bug or problem which is only affecting IE and not the other browsers, and I'm not sure why?

In my case, some jQuery code makes a tooltip appear and disappear with an animation on mouseover and mouseout. In Internet Explorer, it looks awful, and jittery, with the tooltip div changing to a really large size before hiding, and if you run your mouse over a heap of items with the tip it really kills the browser. I have no idea what particular feature IE doesn't "support" that I should be testing against, so it's much easier to just sniff for IE and use a different method. What could/should I do instead?

Answers:

Answer

Because just sniffing the user agent (which is what jquery does to populate the $.browser object) doesn't tell you the whole truth.

The user agent string can be easily changed in many browsers, so if you for example disable some features that don't work in IE from everybody who seems to be using IE, you might accidentally disable those features from some future browsers or users who just, for some reason (like for example to get around limitations based on browser sniffing), pretend to be using IE.

This might not seem too big of a problem, but it is still bad practice.

And yes, I am a IE sniffer too. I use

$.browser.msie && document.all

just to be sure.

Answer

This first thing to note is that user agent sniffing does not just mean looking at navigator.userAgent, it is a general term to describe the large array of methods that people use to change behaviour based on what they believe the browser is.

So the problem is not looking at the user agent string, the problem is deciding what your site should do based on what you think the browser is. This means you may unavoidably limit or break your site in the future; For instance I have seen multiple canvas demos which block IE. They aren't checking to see whether canvas is supported, they are explicitly looking for IE, and if they see it they say IE is broken, this means that even if IE did eventually support canvas these sites still wouldn't work.

Rather than browser sniffing you should always attempt to detect the feature or bug you are interested in. The most common example of these tests is "object detection", eg. document.createElement("canvas").getContext is how the existence of canvas should be detected, and will correctly pick up canvas in any browser, even if current versions don't support it.

Answer

As well as the issues about browser-sniffing being inferior to capability-sniffing, handling navigator.userAgent as a string is in itself a very unreliable way of browser-sniffing.

It might work better if every browser stuck to the “Name/version” scheme of identifying themselves, but they don't. Most browsers claim to be “Mozilla/some.version” regardless of what they are. And that bit at the start is the only readily parsable part of the string; the rest is completely unstandardised. So scripts started searching the whole string for characterists substrings like “MSIE”. This is a disaster.

  • Some browsers deliberately spoof each other, including substrings like “MSIE”, “Gecko” and “Safari” in their user agent strings when they're not those browsers, mostly to defeat ill-conceived string sniffers.

  • Some browsers allow the entire user agent string to be spoofed under user control.

  • Some browser variants aren't. For example IE Mobile is nothing at all like regular IE, but “MSIE” will still match it.

  • Some browsers allow add-ons to write extra tokens to the user agent string including arbitrary text. Just one registry change by a rogue add-on can make MSIE look like Firefox.

  • String matching is just inherently unreliable. For example a new browser called “CLUMSIERbrowser” would match MSIE.

Answer

Because if you get it wrong, you may accidentally cut off features to future browsers that support them.

I often find it useful. I know IE6 doesn't support alpha transparency, so I use browser sniffing to detect IE6 and hide/change elements that use them.

Also for running the mouse over quickly numerous times, try HoverIntent. It users setTimeout() I believe to only fire events when the mouse has been over an element for a brief period of time, saving cycles and avoiding queuing up of events and potentially freezing the browser.

Personally, I preferred jQuery with the browser version/type methods. It could be used to show a friendly hello message based on browser. Maybe jQuery deprecated it due to pressure that 'browser sniffing is evil'.

Update

This is what John Resig (creator of jQuery) says:

We're keeping jQuery.browser for the foreseeable future but we want developers to move away from using it - and the best way to get developers to do that is to become a good example of proper development patterns.

To be clear: The points included in $.support are mostly browser bug specific (IE bugs that can't be tested with normal object detection) - and they don't encompass every possible bug (only about a dozen or so). It's expected that other developers will add their own testing points in the future.

Also, in that commit I forgot to land the actual support.js file - it can be found here: http://dev.jquery.com/browser/trunk/jquery/src/support.js?rev=5986

Source: http://www.reddit.com/r/programming/comments/7l2mr/jquery_removes_all_browser_sniffing/

Also see: http://dev.jquery.com/changeset/5985

Answer

I use a combination of stuff I learned from the HTML5 boilerplate and jquery, so using the IE conditional comments to determine IE version, then test for the existance of these classes. Therefore the HTML would have this at the top:

<!--[if lt IE 7 ]> <html class="no-js ie6" lang="en"> <![endif]-->
<!--[if IE 7 ]>    <html class="no-js ie7" lang="en"> <![endif]-->
<!--[if IE 8 ]>    <html class="no-js ie8" lang="en"> <![endif]-->
<!--[if IE 9 ]>    <html class="no-js ie9" lang="en"> <![endif]-->
<!--[if (gte IE 9)|!(IE)]><!--> <html class="no-js" lang="en"> <!--<![endif]-->

Then I would go on to test for the existance of .ie6, .ie7 etc in jquery like this:

if($('.ie6, .ie7').length > 0){
    // your conditional stuff here
}

Works well for me.

NOTE: Obviously this only tests for IE versions but most other browsers don't cause the issues that IE always does these days and it's much safer than testing the user agent!

Answer

It's not recommended because browsers lie about who they are. See http://farukat.es/journal/2011/02/499-lest-we-forget-or-how-i-learned-whats-so-bad-about-browser-sniffing (an article by the author of the modernizr library).

Also, it is inherently not future-proof. From the article:

Browser sniffing is a technique in which you make assumptions about how a piece of code will work in the future. Generally this means making an assumption that a specific browser bug will always be there - which frequently leads to code breaking when browsers make changes and fix bugs.

Feature detection is recommended as it's much simpler, makes for clearer intent in code, and avoids the issue entirely of browsers lying about who they are.

Answer

Sniff for features, not for useragents. Pseudocode:

if (browser.supports('feature')){
    //execute feature
}

else{
    //fallback
}

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.