[html] Correct way to use Modernizr to detect IE?

I wanted to use the Modernizr JS library to detect for some browser properties to determine what content to show or not show.

I have an app called Pano2VR which outputs both HTML5 and SWF. I need the HTML5 for iOS device users.

However, IE does not render this "HTML5" output at all. It seems their output uses CSS3 3D transforms and WebGL, one or more apparently unsupported in IE9.

So, for those users I need to display the Flash version. I was planning to use an IFRAME and either pass the SRC via a Modernizr script or document.write out the correct IFRAME code depending on browser.

All of which leads to how do I use Modernizr to detect simply IE or not IE? Or detect for CSS 3d transforms?

Or is there another way to do this?

This question is related to html cross-browser modernizr

The answer is


If you're looking for a JS version (using a combination of feature detection and UA sniffing) of what html5 boilerplate used to do:

var IE = (!! window.ActiveXObject && +(/msie\s(\d+)/i.exec(navigator.userAgent)[1])) || NaN;
if (IE < 9) {
    document.documentElement.className += ' lt-ie9' + ' ie' + IE;
}

You can use the < !-- [if IE] > hack to set a global js variable that then gets tested in your normal js code. A bit ugly but has worked well for me.


Well, after doing more research on this topic I ended up using following solution for targeting IE 10+. As IE10&11 are the only browsers which support the -ms-high-contrast media query, that is a good option without any JS:

@media screen and (-ms-high-contrast: active), screen and (-ms-high-contrast: none) {  
   /* IE10+ specific styles go here */  
}

Works perfectly.


CSS tricks have a good solution to target IE 11:

http://css-tricks.com/ie-10-specific-styles/

The .NET and Trident/7.0 are unique to IE so can be used to detect IE version 11.

The code then adds the User Agent string to the html tag with the attribute 'data-useragent', so IE 11 can be targeted specifically...


Modernizr doesn't detect browsers as such, it detects which feature and capability are present and this is the whole jist of what it's trying to do.

You could try hooking in a simple detection script like this and then using it to make your choice. I've included Version Detection as well just in case that's needed. If you only want to check of any version of IE you could just look for the navigator.userAgent having a value of "MSIE".

_x000D_
_x000D_
var BrowserDetect = {_x000D_
        init: function () {_x000D_
            this.browser = this.searchString(this.dataBrowser) || "Other";_x000D_
            this.version = this.searchVersion(navigator.userAgent) || this.searchVersion(navigator.appVersion) || "Unknown";_x000D_
        },_x000D_
        searchString: function (data) {_x000D_
            for (var i = 0; i < data.length; i++) {_x000D_
                var dataString = data[i].string;_x000D_
                this.versionSearchString = data[i].subString;_x000D_
_x000D_
                if (dataString.indexOf(data[i].subString) !== -1) {_x000D_
                    return data[i].identity;_x000D_
                }_x000D_
            }_x000D_
        },_x000D_
        searchVersion: function (dataString) {_x000D_
            var index = dataString.indexOf(this.versionSearchString);_x000D_
            if (index === -1) {_x000D_
                return;_x000D_
            }_x000D_
_x000D_
            var rv = dataString.indexOf("rv:");_x000D_
            if (this.versionSearchString === "Trident" && rv !== -1) {_x000D_
                return parseFloat(dataString.substring(rv + 3));_x000D_
            } else {_x000D_
                return parseFloat(dataString.substring(index + this.versionSearchString.length + 1));_x000D_
            }_x000D_
        },_x000D_
_x000D_
        dataBrowser: [_x000D_
            {string: navigator.userAgent, subString: "Edge", identity: "MS Edge"},_x000D_
            {string: navigator.userAgent, subString: "MSIE", identity: "Explorer"},_x000D_
            {string: navigator.userAgent, subString: "Trident", identity: "Explorer"},_x000D_
            {string: navigator.userAgent, subString: "Firefox", identity: "Firefox"},_x000D_
            {string: navigator.userAgent, subString: "Opera", identity: "Opera"},  _x000D_
            {string: navigator.userAgent, subString: "OPR", identity: "Opera"},  _x000D_
_x000D_
            {string: navigator.userAgent, subString: "Chrome", identity: "Chrome"}, _x000D_
            {string: navigator.userAgent, subString: "Safari", identity: "Safari"}       _x000D_
        ]_x000D_
    };_x000D_
    _x000D_
    BrowserDetect.init();_x000D_
    document.write("You are using <b>" + BrowserDetect.browser + "</b> with version <b>" + BrowserDetect.version + "</b>");
_x000D_
_x000D_
_x000D_

You can then simply check for:

BrowserDetect.browser == 'Explorer';
BrowserDetect.version <= 9;

You can use Modernizr to detect simply IE or not IE, by checking for SVG SMIL animation support.

If you've included SMIL feature detection in your Modernizr setup, you can use a simple CSS approach, and target the .no-smil class that Modernizr applies to the html element:

html.no-smil {
  /* IE/Edge specific styles go here - hide HTML5 content and show Flash content */
}

Alternatively, you could use Modernizr with a simple JavaScript approach, like so:

if ( Modernizr.smil ) {
  /* set HTML5 content */
} else {
  /* set IE/Edge/Flash content */
}

Bear in mind, IE/Edge might someday support SMIL, but there are currently no plans to do so.

For reference, here's a link to the SMIL compatibility chart at caniuse.com.


Detecting CSS 3D transforms

Modernizr can detect CSS 3D transforms, yeah. The truthiness of Modernizr.csstransforms3d will tell you if the browser supports them.

The above link lets you select which tests to include in a Modernizr build, and the option you're looking for is available there.


Detecting IE specifically

Alternatively, as user356990 answered, you can use conditional comments if you're searching for IE and IE alone. Rather than creating a global variable, you can use HTML5 Boilerplate's <html> conditional comments trick to assign a class:

<!--[if lt IE 7]>      <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]>         <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]>         <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->

If you already have jQuery initialised, you can just check with $('html').hasClass('lt-ie9'). If you need to check which IE version you're in so you can conditionally load either jQuery 1.x or 2.x, you can do something like this:

myChecks.ltIE9 = (function(){
    var htmlElemClasses = document.querySelector('html').className.split(' ');
    if (!htmlElemClasses){return false;}
    for (var i = 0; i < htmlElemClasses.length; i += 1 ){
      var klass = htmlElemClasses[i];
      if (klass === 'lt-ie9'){
        return true;
      }
    }
    return false;
}());

N.B. IE conditional comments are only supported up to IE9 inclusive. From IE10 onwards, Microsoft encourages using feature detection rather than browser detection.


Whichever method you choose, you'd then test with

if ( myChecks.ltIE9 || Modernizr.csstransforms3d ){
    // iframe or flash fallback
} 

Don't take that || literally, of course.


I needed to detect IE vs most everything else and I didn't want to depend on the UA string. I found that using es6number with Modernizr did exactly what I wanted. I don't have much concern with this changing as I don't expect IE to ever support ES6 Number. So now I know the difference between any version of IE vs Edge/Chrome/Firefox/Opera/Safari.

More details here: http://caniuse.com/#feat=es6-number

Note that I'm not really concerned about Opera Mini false negatives. You might be.