Why is browser sniffing not a recommended practice?
Asked Answered
D

7

16

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?

Dicrotic answered 19/3, 2009 at 6:13 Comment(6)
You could post some more information about your specific problem...Cherellecheremis
For IE you can use conditional comments, a feature only supported by MSIE: msdn.microsoft.com/en-us/library/ms537512.aspxAsynchronism
@markt: i'm not so much interested in solving this specific problem as the general problem of browser sniffing. @some: isn't that just as bad?Dicrotic
IMHO no. Firefox, Opera and Chrome usually behaves similar enough. But to get it to work in IE you sometimes need different html/css/javascript. The beautiful thing with conditional comments is that it is easy to get the real (not spoofed) IE to get the special code. You can even target it to a specific version of IE or platform IIRC.Asynchronism
This is something you may find interesting. Just like Dilbert comics I know I found it funny..... and somehow depressing.Mccaskill
Detecting feature over browser is considered as a good practice. On Windows, I use compact inspector with fiddler to detect if the script running on the website is using browser sniffing.Unceremonious
B
10

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.

Bujumbura answered 19/3, 2009 at 6:33 Comment(3)
Why on earth would someone pretend to be IE? hahaTopsyturvydom
Well, one good example would be to use sites that user browser sniffing and deny access from non-IE users :)Bujumbura
Oh yes, that used to be the case for my online banking site. It would deny Firefox. Thankfully though, that's been cleared up for some time.Topsyturvydom
G
6

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.

Gemology answered 19/3, 2009 at 7:30 Comment(0)
R
4

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.

Rosary answered 19/3, 2009 at 7:16 Comment(0)
T
2

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

Topsyturvydom answered 19/3, 2009 at 6:19 Comment(1)
Note too the Mozilla in User Agent strings comes from back in the days when Mozilla (Mosaic Killer) was the best browser and competitors wanted to imitate it.Topsyturvydom
M
2

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!

Moujik answered 19/1, 2012 at 14:26 Comment(1)
Yeah, but as I said in the comments of the OP, these conditional comments are really just another form of browser sniffing. Yes, they're more reliable since a user isn't able to mess with it like they could a user agent string, but it's definitely not performing feature tests as you're "supposed" to do.Dicrotic
B
2

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.

Blithesome answered 14/8, 2013 at 14:36 Comment(1)
Cleanest clearest answer. Browsers lie about who they are, and code changes.Flabby
M
1

Sniff for features, not for useragents. Pseudocode:

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

else{
    //fallback
}
Millwork answered 12/11, 2013 at 20:12 Comment(2)
If someone can explain to me why this is downvoted, that would be great. makeameme.org/media/templates/250/…Millwork
I think that you are not explaining why is better to sniff for features, so you are not trying to answer question being asked. (but I didn't downvote you so I can't be sure)Inseparable

© 2022 - 2024 — McMap. All rights reserved.