Browser detection versus feature detection
It seems to me browser detection has been widely frowned upon since this post by Resig a couple of years ago. Resig's comments however were specific to libraries/framework code, i.e. code that will be consumed by other [domain-specific] applications/sites.
I think feature detection is without question a good fit for libraries/frameworks. For domain-specific applications however I'm not so sure browser detection is that bad. It's suitable for working around known browser characteristics that are difficult to feature-detect, or for browsers that have bugs in their implementation of the feature itself. Times that browser detection is appropriate:
- sites/applications that are not cross-browser and need to show a warning/dialog/DifferentPage tailoring to that client's browser. This is common in legacy applications.
- Banks or private sites with strict policies on what browsers and versions are supported (to avoid known security exploits that may compromise user's data)
- micro-optimizations: occasionally one browser is ridiculously faster than the others when performing some operation a certain way. It can be advantageous depending on your user base to branch on that particular browser/version.
- Lack of png transparency in IE6
- many display/rendering issues (read: IE css support) that are only witnessed in specific browser versions and you don't actually know what feature to test for.
That said, there are some major pitfalls (probably committed by most of us) to avoid when doing browser detection.
What's the difference between feature detection, feature inference, and using the UA string
Feature detection checks a feature for existence, e.g.:
if (window.XMLHttpRequest) {
new XMLHttpRequest();
}
Feature inference checks for a feature just like feature detection, but uses another function because it assumes it will also exist, e.g.:
if (document.getElementsByTagName) {
element = document.getElementById(id);
}
Checking the UA string is an old practice and should not be used anymore. You keep changing the UA checks and never benefit from newly implemented features, e.g.:
if (navigator.userAgent.indexOf("MSIE 7") > -1){
//do something
}
What is the means, benefit and differences between User Agent detection and Feature Detection?
The main reason to use feature detection as opposed to user agent sniffing is future proofing.
Let's say, for example, that you want to use some new XMLHttpRequest 2.0 features (just making this up). You know IE doesn't support it but Firefox does, and so you have code like this in your JS:
if (!IE) {
UseNewAjax();
} else {
UseOldAjax();
}
Later, a new version of IE comes out which supports the new features, but because you are agent-sniffing, your IE viewers can't get this feature goodness without you making a change to your code.
On the other hand, if you feature detection:
if (document.hasCoolNewAjax) {
UseNewAjax();
} else {
UseOldAjax();
}
You can be assured in the future that if a browser supports a feature they didn't before, they can start using these features immediately, and you don't have to change your code to support it.
Browser / User Agent sniffing: Using a programming language to determine what browser a visitor is using, so special logic can be written against that browser. Inefficient and considered a bad practice in the development community.
Feature detection: Using a programming language to determine whether a browser supports a particular feature. Considered a best practice in the developer community because it is fool-proof and future-proof.
From Wikipedia:
User agent sniffing is mostly considered poor practice, since it encourages browser-specific design and penalizes new browsers with unrecognized user agent identifications. Instead, the W3C recommends creating HTML markup that is standard,[citation needed] allowing correct rendering in as many browsers as possible, and to test for specific browser features rather than particular browser versions or brands.
JavaScript isn't the only language which you can user-agent sniff or feature detect from. For example, the .NET framework has properties that let you read all sorts of information about the browser:
http://msdn.microsoft.com/en-us/library/3yekbd5b.aspx
http://modernizr.com
JavaScript: Partial Feature Detection (srcset)
What is wrong with one of these polyfills:
- https://github.com/scottjehl/picturefill
- https://github.com/aFarkas/respimage
Or a partial polyfill like this one:
- https://github.com/aFarkas/lazysizes/tree/gh-pages/plugins/respimg
Detecting whether a browser supports the width descriptor is quite easy, if you have basic JS and responsive image knowledge.
Therefore, I really would suggest that you use one of the polyfills above.
var img = document.createElement('img');
var isWSupported = ('sizes' in img);
JS feature detection to detect the usage of -webkit-calc over calc
Create a dummy element, insert it in the document, use .cssText.height = 'calc(100px - 50px);'
, and check if the element has the expected height. Repeat this for every vendor-prefix.
Side note: For this kind of questions, you should look in the source code of Modernizr. Others have usually contributed such feature detection scripts, such as calc.js
.
Modernizr detects whether the feature is present, it doesn't tell which prefix has to be used. The code below shows how to get the correct prefix:
var calc = (function(){
var dummy = document.createElement('div');
var props = ['calc', '-webkit-calc', '-moz-calc', '-o-calc'];
for (var i=0; i<props.length; ++i) {
var prop = props[i];
dummy.style.cssText = 'width:' + prop + '(1px);';
if (dummy.style.length)
return prop;
}
})();
// Usage example:
$('selector').css('height', calc + '(100% / 3)');
(I did not add the -ms-
prefix, because IE started supporting it without the prefix - see http://caniuse.com/calc.)
Related Topics
Jquery Load() Only Working in Firefox
Why Does This Simple Jsfiddle Not Work
How to Set Html5 Required Attribute in JavaScript
How to Insert a Row in an HTML Table Body in JavaScript
JavaScript - Append HTML to Container Element Without Innerhtml
Get the Position of a Div/Span Tag
How to Validate an Email Address in JavaScript
Launch Bootstrap Modal on Page Load
How Exactly Does ≪Script Defer="Defer"≫ Work
Get City Name Using Geolocation
How to Scroll to an Element Inside a Div
Difference Between ≪Script Src="Foo.Js"≫≪/Script≫ and ≪Script Src="Foo.Js"/≫
How to Reload Current Page Without Losing Any Form Data
Capture Iframe Load Complete Event
How to Get the Element Clicked (For the Whole Document)
Do Dom Tree Elements With Ids Become Global Properties
Replacing CSS File on the Fly (And Apply the New Style to the Page)