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?

casperOne
  • 73,706
  • 19
  • 184
  • 253
nickf
  • 537,072
  • 198
  • 649
  • 721
  • You could post some more information about your specific problem... – markt Mar 19 '09 at 06:18
  • For IE you can use conditional comments, a feature only supported by MSIE: http://msdn.microsoft.com/en-us/library/ms537512.aspx – some Mar 19 '09 at 08:20
  • @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? – nickf Mar 19 '09 at 23:18
  • 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. – some Jun 11 '09 at 18:14
  • This is something you may find interesting. Just like Dilbert comics I know I found it funny..... and somehow depressing. – Bryan Jul 20 '09 at 20:10
  • 1
    Detecting [feature over browser](http://msdn.microsoft.com/en-us/library/ff986088%28v=vs.85%29.aspx) is considered as a good practice. On Windows, I use [compact inspector with fiddler](http://blogs.msdn.com/b/ie/archive/2012/01/20/ie10-compat-inspector.aspx) to detect if the script running on the website is using browser sniffing. – Annie Nov 27 '12 at 23:25

7 Answers7

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.

kkyy
  • 12,214
  • 3
  • 32
  • 27
  • 19
    Why on earth would someone pretend to be IE? haha – alex Mar 19 '09 at 06:36
  • 3
    Well, one good example would be to use sites that user browser sniffing and deny access from non-IE users :) – kkyy Mar 19 '09 at 06:38
  • 1
    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. – alex Mar 19 '09 at 06:44
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.

olliej
  • 35,755
  • 9
  • 58
  • 55
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.

bobince
  • 528,062
  • 107
  • 651
  • 834
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.

jinglesthula
  • 4,446
  • 4
  • 45
  • 79
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

alex
  • 479,566
  • 201
  • 878
  • 984
  • 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. – alex Mar 19 '09 at 10:06
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!

Matthew
  • 31
  • 3
  • 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. – nickf Jan 20 '12 at 09:27
1

Sniff for features, not for useragents. Pseudocode:

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

else{
    //fallback
}
user2019515
  • 4,495
  • 1
  • 29
  • 42
  • If someone can explain to me why this is downvoted, that would be great. http://makeameme.org/media/templates/250/that_would_be_great_office_space_bill_lumbergh.jpg – user2019515 Nov 16 '13 at 03:35
  • 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)* – eloyesp Dec 26 '13 at 12:20