Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
// ----------------------------------------------------------
// A short snippet for detecting versions of IE in JavaScript
// without resorting to user-agent sniffing
// ----------------------------------------------------------
// If you're not in IE (or IE version is less than 5) then:
// ie === undefined
// If you're in IE (>=5) then you can determine which version:
// ie === 7; // IE7
// Thus, to detect IE:
// if (ie) {}
// And to detect the version:
// ie === 6 // IE6
// ie > 7 // IE8, IE9 ...
// ie < 9 // Anything less than IE9
// ----------------------------------------------------------
// UPDATE: Now using Live NodeList idea from @jdalton
var ie = (function(){
var undef,
v = 3,
div = document.createElement('div'),
all = div.getElementsByTagName('i');
while (
div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->',
all[0]
);
return v > 4 ? v : undef;
}());
@jdalton

This comment has been minimized.

Show comment Hide comment
@jdalton

jdalton Aug 16, 2010

This is hawt. I love the way you use the expression in the while statement though it could be done with a do-while for clarity. Very cool :{D

jdalton commented Aug 16, 2010

This is hawt. I love the way you use the expression in the while statement though it could be done with a do-while for clarity. Very cool :{D

@paulirish

This comment has been minimized.

Show comment Hide comment
@paulirish

paulirish Aug 16, 2010

hawt +1

hawt +1

@miketaylr

This comment has been minimized.

Show comment Hide comment
@miketaylr

miketaylr Aug 16, 2010

This would be even awesomer with some in-line notes explaining the magic. :) Nice work!

This would be even awesomer with some in-line notes explaining the magic. :) Nice work!

@zachleat

This comment has been minimized.

Show comment Hide comment
@zachleat

zachleat Aug 16, 2010

Pretty sweet, especially useful since I've seen some user agents where it has two different IE versions listed. http://www.zachleat.com/web/2008/10/19/jquery-bug-ie-reports-incorrect-browserversion/

Pretty sweet, especially useful since I've seen some user agents where it has two different IE versions listed. http://www.zachleat.com/web/2008/10/19/jquery-bug-ie-reports-incorrect-browserversion/

@jdalton

This comment has been minimized.

Show comment Hide comment
@jdalton

jdalton Aug 17, 2010

A bit smaller and returns false instead of undefined for non IE browsers:

var ie = (function() {

    var v = 3, div = document.createElement('div'), a = div.all || [];

    while (div.innerHTML = '<!--[if gt IE '+(++v)+']><br><![endif]-->', a[0]); 

    return v > 4 ? v : !v;

}());

jdalton commented Aug 17, 2010

A bit smaller and returns false instead of undefined for non IE browsers:

var ie = (function() {

    var v = 3, div = document.createElement('div'), a = div.all || [];

    while (div.innerHTML = '<!--[if gt IE '+(++v)+']><br><![endif]-->', a[0]); 

    return v > 4 ? v : !v;

}());
@aheckmann

This comment has been minimized.

Show comment Hide comment
@aheckmann

aheckmann Aug 17, 2010

neato

neato

@paulirish

This comment has been minimized.

Show comment Hide comment
@paulirish

paulirish Aug 17, 2010

@zach: Ben Alman, Resig and I revised the UA sniffing for jQuery 1.4 in January so the issue from your post has since been resolved.

I'll take a crack at documenting James' original:

    var ie = (function(){

        var undef, v = 3, div = document.createElement('div');

        // the while loop is used without an associated block: {}
        // so, only the condition within the () is executed.

        // semicolons arent allowed within the condition,
        //   so a comma is used to stand in for one
        // basically allowing the two separate statements 
        //   to be evaluated sequentially.

        while (
            div.innerHTML = '<!--[if gt IE '+(++v)+']><i></i><![endif]-->',
            div.getElementsByTagName('i')[0]
        );

        // each time it's evaluated, v gets incremented and
        //   tossed into the DOM as a conditional comment
        // the i element is then a child of the div.

        // the return value of the getEBTN call is used as 
        //   the final condition expression
        // if there is an i element (the IE conditional
        //   succeeded), then getEBTN's return is truthy
        // and the loop continues until there is no 
        //   more i elements.

        // In other words:  ** MAGIC**

        return v > 4 ? v : undef;

    }());

@zach: Ben Alman, Resig and I revised the UA sniffing for jQuery 1.4 in January so the issue from your post has since been resolved.

I'll take a crack at documenting James' original:

    var ie = (function(){

        var undef, v = 3, div = document.createElement('div');

        // the while loop is used without an associated block: {}
        // so, only the condition within the () is executed.

        // semicolons arent allowed within the condition,
        //   so a comma is used to stand in for one
        // basically allowing the two separate statements 
        //   to be evaluated sequentially.

        while (
            div.innerHTML = '<!--[if gt IE '+(++v)+']><i></i><![endif]-->',
            div.getElementsByTagName('i')[0]
        );

        // each time it's evaluated, v gets incremented and
        //   tossed into the DOM as a conditional comment
        // the i element is then a child of the div.

        // the return value of the getEBTN call is used as 
        //   the final condition expression
        // if there is an i element (the IE conditional
        //   succeeded), then getEBTN's return is truthy
        // and the loop continues until there is no 
        //   more i elements.

        // In other words:  ** MAGIC**

        return v > 4 ? v : undef;

    }());
@zachleat

This comment has been minimized.

Show comment Hide comment
@zachleat

zachleat Aug 17, 2010

Yeah, the jQuery team was very quick to patch it up, just offering as evidence that UA strings can be corrupted.

Yeah, the jQuery team was very quick to patch it up, just offering as evidence that UA strings can be corrupted.

@wavded

This comment has been minimized.

Show comment Hide comment
@wavded

wavded Aug 17, 2010

+1 on the hawtness

wavded commented Aug 17, 2010

+1 on the hawtness

@dperini

This comment has been minimized.

Show comment Hide comment
@dperini

dperini Aug 17, 2010

Cool !
The "&&" operator could be used instead of the comma as another variation to continue the expression in the while.
But yes the comma is one byte less ;-)

dperini commented Aug 17, 2010

Cool !
The "&&" operator could be used instead of the comma as another variation to continue the expression in the while.
But yes the comma is one byte less ;-)

@miketaylr

This comment has been minimized.

Show comment Hide comment
@miketaylr

miketaylr Aug 17, 2010

Nice comments Paul!

Nice comments Paul!

@phiggins42

This comment has been minimized.

Show comment Hide comment
@phiggins42

phiggins42 Aug 17, 2010

this is hawt. My first inclination was to replace the d.isIE sniff for this, but have to consider CLA. bummer.

this is hawt. My first inclination was to replace the d.isIE sniff for this, but have to consider CLA. bummer.

@jdalton

This comment has been minimized.

Show comment Hide comment
@jdalton

jdalton Aug 17, 2010

To compliment Paul's explanation I will get a bit more specy.
Paul is mixing up the terms Statement and Expression in his explanation of the while statement.

A while statement is made of the following parts
while ( Expression ) Statement

In James' example
while(a.prop=c, d.method()[0]);

spec-ifies to

while ( AssignmentExpression, Expression ) EmptyStatement

and could be broken down to

while ( LeftHandSideExpression = AssignmentExpression, CallExpression [ Expression ] ) EmptyStatement

and could be broken down even further.

There is no semi-colon in the expression because that would create an ExpressionStatement which is a Statement not an Expression.

jdalton commented Aug 17, 2010

To compliment Paul's explanation I will get a bit more specy.
Paul is mixing up the terms Statement and Expression in his explanation of the while statement.

A while statement is made of the following parts
while ( Expression ) Statement

In James' example
while(a.prop=c, d.method()[0]);

spec-ifies to

while ( AssignmentExpression, Expression ) EmptyStatement

and could be broken down to

while ( LeftHandSideExpression = AssignmentExpression, CallExpression [ Expression ] ) EmptyStatement

and could be broken down even further.

There is no semi-colon in the expression because that would create an ExpressionStatement which is a Statement not an Expression.

@padolsey

This comment has been minimized.

Show comment Hide comment
@padolsey

padolsey Aug 17, 2010

Sorry about not adding comments to the original -- thanks Paul for adding some!

Thanks @jdalton for the improvement! I forgot about the whole live NodeList thing... very cool!

Owner

padolsey commented Aug 17, 2010

Sorry about not adding comments to the original -- thanks Paul for adding some!

Thanks @jdalton for the improvement! I forgot about the whole live NodeList thing... very cool!

@marcelkorpel

This comment has been minimized.

Show comment Hide comment
@marcelkorpel

marcelkorpel Aug 17, 2010

Awesome script!

Your comment If you're in IE (>5) is wrong. It should read If you're in IE (>=5)

Awesome script!

Your comment If you're in IE (>5) is wrong. It should read If you're in IE (>=5)

@SlexAxton

This comment has been minimized.

Show comment Hide comment
@SlexAxton

SlexAxton Aug 17, 2010

@james you should totally sign a CLA so this can get added to dojo. It's superduper easy!

@james you should totally sign a CLA so this can get added to dojo. It's superduper easy!

@padolsey

This comment has been minimized.

Show comment Hide comment
@padolsey

padolsey Aug 17, 2010

@marcel, thanks, corrected.

@SlexAxton, Okay, where do I go to sign?

Owner

padolsey commented Aug 17, 2010

@marcel, thanks, corrected.

@SlexAxton, Okay, where do I go to sign?

@padolsey

This comment has been minimized.

Show comment Hide comment
@padolsey

padolsey Aug 17, 2010

@jdalton, just noticed -- with yours, since it returns false, expressions like ie < 7 cannot be used because ie will be false and Number(false) is 0, and therefore the expression ie < 7 will return true in non-IE browsers.

I chose undefined as the non-IE return value because Number(undefined) is NaN and this means the following expressions can be used everywhere (without wrong results in non IE browsers):

 ie === 6 // IE6
 ie > 7 // IE8, IE9 ...
 ie < 9 // Anything less than IE9:
Owner

padolsey commented Aug 17, 2010

@jdalton, just noticed -- with yours, since it returns false, expressions like ie < 7 cannot be used because ie will be false and Number(false) is 0, and therefore the expression ie < 7 will return true in non-IE browsers.

I chose undefined as the non-IE return value because Number(undefined) is NaN and this means the following expressions can be used everywhere (without wrong results in non IE browsers):

 ie === 6 // IE6
 ie > 7 // IE8, IE9 ...
 ie < 9 // Anything less than IE9:
@padolsey

This comment has been minimized.

Show comment Hide comment
@padolsey

padolsey Aug 17, 2010

@dperini, plus, using && would require the first expression (div.innerHTML = ...) to be wrapped in parens, as && has a higher precedence than =.

Owner

padolsey commented Aug 17, 2010

@dperini, plus, using && would require the first expression (div.innerHTML = ...) to be wrapped in parens, as && has a higher precedence than =.

@jdalton

This comment has been minimized.

Show comment Hide comment
@jdalton

jdalton Aug 17, 2010

@james good point on false vs undefined

jdalton commented Aug 17, 2010

@james good point on false vs undefined

@SlexAxton

This comment has been minimized.

Show comment Hide comment
@SlexAxton

SlexAxton Aug 17, 2010

@james http://www.dojofoundation.org/cla/ -- You can just scan it or take a picture of it or something. Then you can be a Dojo Committer!

@james http://www.dojofoundation.org/cla/ -- You can just scan it or take a picture of it or something. Then you can be a Dojo Committer!

@paulirish

This comment has been minimized.

Show comment Hide comment
@paulirish

paulirish Aug 20, 2010

YUICompressor hates and ClosureCompiler strips (!) the /*@cc_on conditional compilation action..

Not the end of the world here, but fair warning.

YUICompressor hates and ClosureCompiler strips (!) the /*@cc_on conditional compilation action..

Not the end of the world here, but fair warning.

@marcelkorpel

This comment has been minimized.

Show comment Hide comment
@marcelkorpel

marcelkorpel Aug 20, 2010

Why do you need that early exit anyway? What does it add, apart from a very slight optimization of a function that probably runs only once?

Why do you need that early exit anyway? What does it add, apart from a very slight optimization of a function that probably runs only once?

@dperini

This comment has been minimized.

Show comment Hide comment
@dperini

dperini Aug 20, 2010

@marcel I believe your suggestion is correct, comparing IE4 to a new browser is wrong anyway ;-)

return v > 4 || !v;

should be just enough (and shorter).

dperini commented Aug 20, 2010

@marcel I believe your suggestion is correct, comparing IE4 to a new browser is wrong anyway ;-)

return v > 4 || !v;

should be just enough (and shorter).

@padolsey

This comment has been minimized.

Show comment Hide comment
@padolsey

padolsey Aug 21, 2010

Just got rid of the early exit (with conditional compilation).

@dperini, that'd return false for non-IE browsers...

Owner

padolsey commented Aug 21, 2010

Just got rid of the early exit (with conditional compilation).

@dperini, that'd return false for non-IE browsers...

@cowboy

This comment has been minimized.

Show comment Hide comment
@cowboy

cowboy Aug 21, 2010

@rriveras

This comment has been minimized.

Show comment Hide comment
@rriveras

rriveras Aug 22, 2010

Really handy! Thanks

Really handy! Thanks

@lifesinger

This comment has been minimized.

Show comment Hide comment
@lifesinger

lifesinger Aug 25, 2010

slightly improve to get smaller: http://gist.github.com/548648

slightly improve to get smaller: http://gist.github.com/548648

@peteboere

This comment has been minimized.

Show comment Hide comment
@peteboere

peteboere Aug 27, 2010

How about simply returning NaN instead of an undefined variable?

How about simply returning NaN instead of an undefined variable?

@balupton

This comment has been minimized.

Show comment Hide comment
@balupton

balupton Jan 23, 2011

Great stuff, what's the license? Or is it so small, that it would fall under public domain?...

Great stuff, what's the license? Or is it so small, that it would fall under public domain?...

@padolsey

This comment has been minimized.

Show comment Hide comment
@padolsey

padolsey Jan 23, 2011

@balupton, no worries, public domain.

Owner

padolsey commented Jan 23, 2011

@balupton, no worries, public domain.

@balupton

This comment has been minimized.

Show comment Hide comment
@balupton

balupton Jan 23, 2011

Sweet thanks a lot! and thanks Paul for showcasing this in your latest video :-)

Sweet thanks a lot! and thanks Paul for showcasing this in your latest video :-)

@paulirish

This comment has been minimized.

Show comment Hide comment
@paulirish

paulirish Jan 23, 2011

This bit has actually been incorporated into https://github.com/slexaxton/yepnope.js in the optional !ie prefix.

It's a fantastic bit of javascript.

This bit has actually been incorporated into https://github.com/slexaxton/yepnope.js in the optional !ie prefix.

It's a fantastic bit of javascript.

@zachleat

This comment has been minimized.

Show comment Hide comment
@zachleat

zachleat Feb 4, 2011

Came back to use this, since it's awesome.

But I'm wondering why your counter starts at 3, when you return undefined for <=4. Shouldn't the counter start at 4?

zachleat commented Feb 4, 2011

Came back to use this, since it's awesome.

But I'm wondering why your counter starts at 3, when you return undefined for <=4. Shouldn't the counter start at 4?

@marcelkorpel

This comment has been minimized.

Show comment Hide comment
@marcelkorpel

marcelkorpel Feb 6, 2011

Because James uses a pre-increment to increment v:

div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->'

so the first test actually runs with 4; when the while loop exits immediately, you're probably not using IE at all.

Would he have used a post-increment, then your assumption is correct, but it has the disadvantage that the version number should be decremented afterwards, otherwise the loop will end with v being incremented after the condition to exit the loop has been met.

Because James uses a pre-increment to increment v:

div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->'

so the first test actually runs with 4; when the while loop exits immediately, you're probably not using IE at all.

Would he have used a post-increment, then your assumption is correct, but it has the disadvantage that the version number should be decremented afterwards, otherwise the loop will end with v being incremented after the condition to exit the loop has been met.

@zachleat

This comment has been minimized.

Show comment Hide comment
@zachleat

zachleat Feb 6, 2011

Ah, sure. My bad. Since I've never encountered a false positive for $.browser.msie, I had used that to toggle the test, and only used this script as a more reliable way to find the version number. Thanks.

zachleat commented Feb 6, 2011

Ah, sure. My bad. Since I've never encountered a false positive for $.browser.msie, I had used that to toggle the test, and only used this script as a more reliable way to find the version number. Thanks.

@davidhellsing

This comment has been minimized.

Show comment Hide comment
@davidhellsing

davidhellsing Feb 13, 2011

Anyone know how to make this Lint?

Anyone know how to make this Lint?

@marcelkorpel

This comment has been minimized.

Show comment Hide comment
@marcelkorpel

marcelkorpel Feb 13, 2011

Why? This is valid JavaScript. JSLint is just very restrictive.

Why? This is valid JavaScript. JSLint is just very restrictive.

@davidhellsing

This comment has been minimized.

Show comment Hide comment
@davidhellsing

davidhellsing Feb 13, 2011

@marcel: I didn't ask why... just wondered if anyone ported this to Lint-friendly code.

@marcel: I didn't ask why... just wondered if anyone ported this to Lint-friendly code.

@marcelkorpel

This comment has been minimized.

Show comment Hide comment
@marcelkorpel

marcelkorpel Feb 13, 2011

No, you didn't, but I did. ;)

Anyway, just work around the issues JSLint complains about; e.g., only use a comparison as the condition within parentheses and do the assignment inside a statement, like:

do {
    div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->';
} while (all[0]);

and make ie a local variable.

No, you didn't, but I did. ;)

Anyway, just work around the issues JSLint complains about; e.g., only use a comparison as the condition within parentheses and do the assignment inside a statement, like:

do {
    div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->';
} while (all[0]);

and make ie a local variable.

@joacim-boive

This comment has been minimized.

Show comment Hide comment
@joacim-boive

joacim-boive Sep 1, 2011

Unfortunately this won't work for IE10 as they've dropped support for conditional comments:
http://blogs.msdn.com/b/ie/archive/2011/07/06/html5-parsing-in-ie10.aspx

Unfortunately this won't work for IE10 as they've dropped support for conditional comments:
http://blogs.msdn.com/b/ie/archive/2011/07/06/html5-parsing-in-ie10.aspx

@SlexAxton

This comment has been minimized.

Show comment Hide comment
@SlexAxton

SlexAxton Sep 1, 2011

That's hopefully a good thing since IE10 shouldn't need singling out compared to it's predecessors.

That's hopefully a good thing since IE10 shouldn't need singling out compared to it's predecessors.

@joacim-boive

This comment has been minimized.

Show comment Hide comment
@joacim-boive

joacim-boive Sep 2, 2011

Unfortunately IE10 still needs to be targeted.

Here's on of my latest problem with all versions of IE (including R10 as of today):
http://jsfiddle.net/wG8Rd/2/

Works perfectly in Chrome/Safari and Firefox.

Unfortunately IE10 still needs to be targeted.

Here's on of my latest problem with all versions of IE (including R10 as of today):
http://jsfiddle.net/wG8Rd/2/

Works perfectly in Chrome/Safari and Firefox.

@SlexAxton

This comment has been minimized.

Show comment Hide comment
@SlexAxton

SlexAxton Sep 2, 2011

"Not supporting transforms" is not an IE quirk. This is a case where feature testing would be much more appropriate than IE sniffing.

"Not supporting transforms" is not an IE quirk. This is a case where feature testing would be much more appropriate than IE sniffing.

@joacim-boive

This comment has been minimized.

Show comment Hide comment
@joacim-boive

joacim-boive Sep 2, 2011

That's not the problem. The rotation transform works in IE 7-10 with the supplied example. The problem is that using a transform with opacity and border-radius will mess up the look of the border. (The background won't be transparent.)

border-radius works natively in IE9-10 but they both have the above problem. The easies solution is to skip the opacity, but the browser(s) needs to be targeted for this and thus it's a shame they've removed conditional comments...

That's not the problem. The rotation transform works in IE 7-10 with the supplied example. The problem is that using a transform with opacity and border-radius will mess up the look of the border. (The background won't be transparent.)

border-radius works natively in IE9-10 but they both have the above problem. The easies solution is to skip the opacity, but the browser(s) needs to be targeted for this and thus it's a shame they've removed conditional comments...

@SlexAxton

This comment has been minimized.

Show comment Hide comment
@SlexAxton

SlexAxton Sep 2, 2011

You generally won't have a ton of luck using old proprietary DX Transforms and mixing it with anything. It seems like comparing the DX and the CSS3 ones is a little flawed. It's also guaranteed to be phased out eventually. Something like:

.no-css-transforms .flip {
  background-image:url(flipped-badge.jpg);
}

would be a safe way to not just back-fill IE 6-10, but also mobile browsers or any of the slew of browsers that have issues with transforms.

You generally won't have a ton of luck using old proprietary DX Transforms and mixing it with anything. It seems like comparing the DX and the CSS3 ones is a little flawed. It's also guaranteed to be phased out eventually. Something like:

.no-css-transforms .flip {
  background-image:url(flipped-badge.jpg);
}

would be a safe way to not just back-fill IE 6-10, but also mobile browsers or any of the slew of browsers that have issues with transforms.

@wamatt

This comment has been minimized.

Show comment Hide comment
@wamatt

wamatt Oct 1, 2012

Cool technique, does it matter if IE10 is not detected?

wamatt commented Oct 1, 2012

Cool technique, does it matter if IE10 is not detected?

@thelucid

This comment has been minimized.

Show comment Hide comment
@thelucid

thelucid Nov 13, 2012

Hmm, I wonder if this could be rolled into an IE CSS expression that adds classes to the document. That way HTML5 boilerplate could lose the comments in the HTML and instead shift it to the CSS.

Hmm, I wonder if this could be rolled into an IE CSS expression that adds classes to the document. That way HTML5 boilerplate could lose the comments in the HTML and instead shift it to the CSS.

@Daniel15

This comment has been minimized.

Show comment Hide comment
@Daniel15

Daniel15 Nov 28, 2012

IE10 still supports JavaScript conditional comments, so you could add something like this right below this code snippet:

// IE 10 no longer supports conditional comments in HTML, but does support JavaScript conditional comments
// This will have to be revisited once IE 11 comes out... :(
if (/*@cc_on!@*/false && !ie) {
    ie = 10;

You could potentially do user agent sniffing to ensure that it's indeed IE10.

IE10 still supports JavaScript conditional comments, so you could add something like this right below this code snippet:

// IE 10 no longer supports conditional comments in HTML, but does support JavaScript conditional comments
// This will have to be revisited once IE 11 comes out... :(
if (/*@cc_on!@*/false && !ie) {
    ie = 10;

You could potentially do user agent sniffing to ensure that it's indeed IE10.

@termi

This comment has been minimized.

Show comment Hide comment
@termi

termi Feb 6, 2013

For all how what to detect IE10:
It's almost like @Daniel15 suggestion.

(function() {
  "use strict";
  var tmp = (document["documentMode"] || document.attachEvent) && "ev"
       , msie = tmp 
                  && (tmp = window[tmp + "al"])
                  && tmp("/*@cc_on 1;@*/")
                  && +((/msie (\d+)/i.exec(navigator.userAgent) || [])[1] || 0)
  ;
  return msie || void 0;
})();

user-agent sniffing, yeah :(
But this would work with:

  • any JS-preprocessors (GCC, for example, will delete all comments including conditional comments)
  • with any IDE without errors for "eval" in "strict mode"

And still like @Daniel15 said:
"This will have to be revisited once IE 11 comes out... :("

termi commented Feb 6, 2013

For all how what to detect IE10:
It's almost like @Daniel15 suggestion.

(function() {
  "use strict";
  var tmp = (document["documentMode"] || document.attachEvent) && "ev"
       , msie = tmp 
                  && (tmp = window[tmp + "al"])
                  && tmp("/*@cc_on 1;@*/")
                  && +((/msie (\d+)/i.exec(navigator.userAgent) || [])[1] || 0)
  ;
  return msie || void 0;
})();

user-agent sniffing, yeah :(
But this would work with:

  • any JS-preprocessors (GCC, for example, will delete all comments including conditional comments)
  • with any IDE without errors for "eval" in "strict mode"

And still like @Daniel15 said:
"This will have to be revisited once IE 11 comes out... :("

@ttfkam

This comment has been minimized.

Show comment Hide comment
@ttfkam

ttfkam Mar 2, 2013

Looks like I'm late to the party. Here's my party favor anyway.

var ie = (function(){
    // for-loop saves characters over while
    for( var v = 3,
             // b just as good as a div with 2 fewer characters
             el = document.createElement('b'),
             // el.all instead of el.getElementsByTagName('i')
             // empty array as loop breaker (and exception-avoider) for non-IE and IE10+
             all = el.all || [];
         // i tag not well-formed since we know that IE5-IE9 won't mind
         el.innerHTML = '<!--[if gt IE ' + (++v) + ']><i><![endif]-->',
         all[0];
       );
    // instead of undefined, returns the documentMode for IE10+ compatibility
    // non-IE will still get undefined as before
    return v > 4 ? v : document.documentMode;
}() );

Compatible with "use strict" (tested in Firefox 22 and Chrome 27). Uses no user agent string sniffing. Also compatible with all known JS minifiers as it uses no IE-specific JavaScript comments.

Minifies to 171 bytes.

var ie=function(){for(var a=3,b=document.createElement("b"),c=b.all||[];b.innerHTML="<!--[if gt IE "+ ++a+"]><i><![endif]-->",c[0];);return 4<a?a:document.documentMode}();

Unfortunately, it's now so small that gzip -9 yields 175 bytes.

ttfkam commented Mar 2, 2013

Looks like I'm late to the party. Here's my party favor anyway.

var ie = (function(){
    // for-loop saves characters over while
    for( var v = 3,
             // b just as good as a div with 2 fewer characters
             el = document.createElement('b'),
             // el.all instead of el.getElementsByTagName('i')
             // empty array as loop breaker (and exception-avoider) for non-IE and IE10+
             all = el.all || [];
         // i tag not well-formed since we know that IE5-IE9 won't mind
         el.innerHTML = '<!--[if gt IE ' + (++v) + ']><i><![endif]-->',
         all[0];
       );
    // instead of undefined, returns the documentMode for IE10+ compatibility
    // non-IE will still get undefined as before
    return v > 4 ? v : document.documentMode;
}() );

Compatible with "use strict" (tested in Firefox 22 and Chrome 27). Uses no user agent string sniffing. Also compatible with all known JS minifiers as it uses no IE-specific JavaScript comments.

Minifies to 171 bytes.

var ie=function(){for(var a=3,b=document.createElement("b"),c=b.all||[];b.innerHTML="<!--[if gt IE "+ ++a+"]><i><![endif]-->",c[0];);return 4<a?a:document.documentMode}();

Unfortunately, it's now so small that gzip -9 yields 175 bytes.

@mvjoyner

This comment has been minimized.

Show comment Hide comment
@mvjoyner

mvjoyner Mar 26, 2013

I needed IE10 support, as I was using the imagesloaded plugin in combination with imgrefresh (https://code.google.com/p/image-refresh/) (so to refresh unloaded images in ie), as IE still has issues with cached images! So the check had to be extended to IE10. Here's the code. I'm not a JS guru, so I've probably brutalized it, but it does work now for IE10 -- based on Daniel15's Idea.

If someone wants to make it all sparkly again, by all means.

var ie = (function(){
  var undef,
      v = 3,
      div = document.createElement('div'),
      all = div.getElementsByTagName('i');
  while (
    div.innerHTML = '',
    all[0]
  ) { 
    ver = v;
  }
  //ie10 support
  if (/*@cc_on!@*/false && typeof ver === 'undefined') {
    ver = 10;
  } else {
    ver = 3;
  }

  return ver > 4 ? ver : undef;
}());

I needed IE10 support, as I was using the imagesloaded plugin in combination with imgrefresh (https://code.google.com/p/image-refresh/) (so to refresh unloaded images in ie), as IE still has issues with cached images! So the check had to be extended to IE10. Here's the code. I'm not a JS guru, so I've probably brutalized it, but it does work now for IE10 -- based on Daniel15's Idea.

If someone wants to make it all sparkly again, by all means.

var ie = (function(){
  var undef,
      v = 3,
      div = document.createElement('div'),
      all = div.getElementsByTagName('i');
  while (
    div.innerHTML = '',
    all[0]
  ) { 
    ver = v;
  }
  //ie10 support
  if (/*@cc_on!@*/false && typeof ver === 'undefined') {
    ver = 10;
  } else {
    ver = 3;
  }

  return ver > 4 ? ver : undef;
}());
@ecstaticpeon

This comment has been minimized.

Show comment Hide comment
@ecstaticpeon

ecstaticpeon Jul 10, 2013

Regarding IE 10 detection and following @Daniel15's idea, we can use @_jscript_version instead of the UA (see http://msdn.microsoft.com/en-us/library/ie/s59bkzce%28v=vs.94%29.aspx):

var ie_version = (function() {
    var undef,
        v = 3,
        div = document.createElement('div'),
        all = div.getElementsByTagName('i');

    while (
        div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->',
        all[0]
    );

    return v > 4 ? v : undef;
}());
/*@cc_on
if (typeof(ie_version) == 'undefined') {
    ie_version = parseInt(@_jscript_version);
}
@*/

Note that we could only use that last if statement, but then that would return incorrect version numbers when changing the browser mode.

As mentioned before, this may break in IE 11.

Regarding IE 10 detection and following @Daniel15's idea, we can use @_jscript_version instead of the UA (see http://msdn.microsoft.com/en-us/library/ie/s59bkzce%28v=vs.94%29.aspx):

var ie_version = (function() {
    var undef,
        v = 3,
        div = document.createElement('div'),
        all = div.getElementsByTagName('i');

    while (
        div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->',
        all[0]
    );

    return v > 4 ? v : undef;
}());
/*@cc_on
if (typeof(ie_version) == 'undefined') {
    ie_version = parseInt(@_jscript_version);
}
@*/

Note that we could only use that last if statement, but then that would return incorrect version numbers when changing the browser mode.

As mentioned before, this may break in IE 11.

@nrako

This comment has been minimized.

Show comment Hide comment
@nrako

nrako Aug 15, 2013

Beware I wasted an awful of time on a IE issue related to requirejs trying to eval the last version of this gist submitted by @ecstaticpeon. So if you use this through requirejs and have a http://requirejs.org/docs/errors.html#fromtexteval error msg, it's definitely because of /*@cc_on I just added a space like this /* @cc_on and now the eval() pass. But I didn't tested on IE10 yet... anyway I don't like this conditional compilation stuff, I'll try to find something else.

nrako commented Aug 15, 2013

Beware I wasted an awful of time on a IE issue related to requirejs trying to eval the last version of this gist submitted by @ecstaticpeon. So if you use this through requirejs and have a http://requirejs.org/docs/errors.html#fromtexteval error msg, it's definitely because of /*@cc_on I just added a space like this /* @cc_on and now the eval() pass. But I didn't tested on IE10 yet... anyway I don't like this conditional compilation stuff, I'll try to find something else.

@adrien-be

This comment has been minimized.

Show comment Hide comment
@adrien-be

adrien-be Aug 23, 2013

@nrako: thanks for the heads up. But adding a space like you did does break the code. Try it on http://jsfiddle.net/P5z4N/4/

@nrako: thanks for the heads up. But adding a space like you did does break the code. Try it on http://jsfiddle.net/P5z4N/4/

@adrien-be

This comment has been minimized.

Show comment Hide comment
@adrien-be

adrien-be Aug 23, 2013

@nrako: here is a different version that might work for you :)

Try it on http://jsfiddle.net/e8G3S/1/

// Returns the version of Internet Explorer or a -1 (indicating the use of another browser)
function getInternetExplorerVersion(){
  var rv = -1; // Return value assumes failure.
  if (navigator.appName == 'Microsoft Internet Explorer'){
    var ua = navigator.userAgent;
    var re  = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
    if (re.exec(ua) != null)
      rv = parseFloat( RegExp.$1 );
    }
  return rv;
}
function displayAlert(){
  var msg = "You're not using Internet Explorer.";
  var ver = getInternetExplorerVersion();
  if ( ver > -1 ){
    if ( ver <= 8.0 ){
      msg = "You're using Internet Explorer 8 or below" ;
    }
    else if ( ver >= 9.0 && ver < 10.0 ){
      msg = "You're using IE 9 or above";
    }
    else{
      msg = "You're using IE 10"; 
    }
  }
  alert( msg );
}

@nrako: here is a different version that might work for you :)

Try it on http://jsfiddle.net/e8G3S/1/

// Returns the version of Internet Explorer or a -1 (indicating the use of another browser)
function getInternetExplorerVersion(){
  var rv = -1; // Return value assumes failure.
  if (navigator.appName == 'Microsoft Internet Explorer'){
    var ua = navigator.userAgent;
    var re  = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
    if (re.exec(ua) != null)
      rv = parseFloat( RegExp.$1 );
    }
  return rv;
}
function displayAlert(){
  var msg = "You're not using Internet Explorer.";
  var ver = getInternetExplorerVersion();
  if ( ver > -1 ){
    if ( ver <= 8.0 ){
      msg = "You're using Internet Explorer 8 or below" ;
    }
    else if ( ver >= 9.0 && ver < 10.0 ){
      msg = "You're using IE 9 or above";
    }
    else{
      msg = "You're using IE 10"; 
    }
  }
  alert( msg );
}
@nrako

This comment has been minimized.

Show comment Hide comment
@nrako

nrako Aug 26, 2013

@adrien-be indeed it fail on IE10, the last code you sent is quite different it's solely useragent sniffing, and I still love the conditional comment better, I (and requirejs) just don't like the condition compilation stuff for IE10 detection.

nrako commented Aug 26, 2013

@adrien-be indeed it fail on IE10, the last code you sent is quite different it's solely useragent sniffing, and I still love the conditional comment better, I (and requirejs) just don't like the condition compilation stuff for IE10 detection.

This comment has been minimized.

Show comment Hide comment
@ghost

ghost Sep 10, 2013

Smaller yet? https://gist.github.com/devxdev/6506658

I Can't test I'm on Ubuntu. maybe smaller if undefined isn't required in the last ()

ghost commented Sep 10, 2013

Smaller yet? https://gist.github.com/devxdev/6506658

I Can't test I'm on Ubuntu. maybe smaller if undefined isn't required in the last ()

@moussahoumani

This comment has been minimized.

Show comment Hide comment
@moussahoumani

moussahoumani Nov 3, 2013

The expression in the while statement was done proper though for clarity I'd use a do-while.
Interesting :{D, fail on IE10, the last code you sent looks odd to me mainly because agent sniffing, I find the conditional comment interesting, I and requires just don't like the condition compilation stuff for IE10 detection. Because James uses a pre-increment to increment v:

The expression in the while statement was done proper though for clarity I'd use a do-while.
Interesting :{D, fail on IE10, the last code you sent looks odd to me mainly because agent sniffing, I find the conditional comment interesting, I and requires just don't like the condition compilation stuff for IE10 detection. Because James uses a pre-increment to increment v:

This comment has been minimized.

Show comment Hide comment
@ghost

ghost Nov 7, 2013

(+/-) from the grade listed.

ghost commented Nov 7, 2013

(+/-) from the grade listed.

This comment has been minimized.

Show comment Hide comment
@ghost

ghost Nov 7, 2013

(+/-) from the grade listed.

ghost commented Nov 7, 2013

(+/-) from the grade listed.

This comment has been minimized.

Show comment Hide comment
@ghost

ghost Nov 7, 2013

(+/-) from the grade listed.

ghost commented Nov 7, 2013

(+/-) from the grade listed.

This comment has been minimized.

Show comment Hide comment
@ghost

ghost Nov 7, 2013

(+/-) from the grade listed.

ghost commented Nov 7, 2013

(+/-) from the grade listed.

@davidhellsing

This comment has been minimized.

Show comment Hide comment
@davidhellsing

davidhellsing Nov 22, 2013

I wanted this script to include IE10+11 as well, and my tests works fine by just returning document.documentMode instead of undefined, since it will be undefined for non-IE browsers anyway (I also prefer do...while...):

var ie = (function() {
  var v = 3
    , div = document.createElement( 'div' )
    , all = div.getElementsByTagName( 'i' )
  do
    div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->'
  while 
    (all[0])
  return v > 4 ? v : document.documentMode
}())

I wanted this script to include IE10+11 as well, and my tests works fine by just returning document.documentMode instead of undefined, since it will be undefined for non-IE browsers anyway (I also prefer do...while...):

var ie = (function() {
  var v = 3
    , div = document.createElement( 'div' )
    , all = div.getElementsByTagName( 'i' )
  do
    div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->'
  while 
    (all[0])
  return v > 4 ? v : document.documentMode
}())

This comment has been minimized.

Show comment Hide comment
@ghost

ghost Jan 23, 2014

So I tried the code above, also davidhellsing's version, and I tested this on ie8, and it always says it's version 7, when it's 8. So I don't think this works on ie8.

ghost commented Jan 23, 2014

So I tried the code above, also davidhellsing's version, and I tested this on ie8, and it always says it's version 7, when it's 8. So I don't think this works on ie8.

This comment has been minimized.

Show comment Hide comment
@ghost

ghost Jan 23, 2014

Also, just tried it in ie10 and ie gets declared as undefined.

ghost commented Jan 23, 2014

Also, just tried it in ie10 and ie gets declared as undefined.

@human-a

This comment has been minimized.

Show comment Hide comment
@human-a

human-a Mar 15, 2014

@ttfkam Best Solution for IE10+

human-a commented Mar 15, 2014

@ttfkam Best Solution for IE10+

@alextreppass

This comment has been minimized.

Show comment Hide comment
@alextreppass

alextreppass May 2, 2014

For any future spelunkers, the @davidhellsing version just above works fine on IE8 through IE11

For any future spelunkers, the @davidhellsing version just above works fine on IE8 through IE11

@tadudek

This comment has been minimized.

Show comment Hide comment
@tadudek

tadudek Aug 8, 2014

If I'm testing IE11, but it's forced into ie8 via 'IE=EmulateIE8', this solution from @davidhellsing still show the IE version as 8, not as 11. Any thoughts? I want to determine if it's really IE10/11.

tadudek commented Aug 8, 2014

If I'm testing IE11, but it's forced into ie8 via 'IE=EmulateIE8', this solution from @davidhellsing still show the IE version as 8, not as 11. Any thoughts? I want to determine if it's really IE10/11.

@hayatbiralem

This comment has been minimized.

Show comment Hide comment
@hayatbiralem

hayatbiralem Jun 16, 2015

You can use bowser.

You can use bowser.

@taveras

This comment has been minimized.

Show comment Hide comment
@taveras

taveras Jun 18, 2015

This is slick!

taveras commented Jun 18, 2015

This is slick!

@tamer1an

This comment has been minimized.

Show comment Hide comment
@tamer1an

tamer1an Jul 2, 2015

Unfortunately IE>=10 don't have conditional comments

tamer1an commented Jul 2, 2015

Unfortunately IE>=10 don't have conditional comments

@jeremykohn

This comment has been minimized.

Show comment Hide comment
@jeremykohn

jeremykohn Oct 12, 2015

The best option for IE / Edge these days is probably Layout Engine or something similar that uses JavaScript to detect browser features.

User agents can be forged or altered so I wouldn't rely on UA sniffing.

The best option for IE / Edge these days is probably Layout Engine or something similar that uses JavaScript to detect browser features.

User agents can be forged or altered so I wouldn't rely on UA sniffing.

@Webnewbies

This comment has been minimized.

Show comment Hide comment
@Webnewbies

Webnewbies Jan 18, 2016

Maybe help:

var ie = 'NotIE'; //IE5-11
if( !!document.compatMode ) {
if( !!(Math && Math.acosh) ) ie = 'EDGE 12';
if( !!document.uniqueID){
if(!!window.ActiveXObject){ ie = 11; }
else if(!!document.all){
if(!!window.atob){ie = 10;}
else if(!!document.addEventListener) {ie = 9;}
else if(!!document.querySelector){ie = 8;}
else if(!!window.XMLHttpRequest){ie = 7;}
else if(!!document.compatMode){ie = 6;}
else ie = 5;
}
}
}

Maybe help:

var ie = 'NotIE'; //IE5-11
if( !!document.compatMode ) {
if( !!(Math && Math.acosh) ) ie = 'EDGE 12';
if( !!document.uniqueID){
if(!!window.ActiveXObject){ ie = 11; }
else if(!!document.all){
if(!!window.atob){ie = 10;}
else if(!!document.addEventListener) {ie = 9;}
else if(!!document.querySelector){ie = 8;}
else if(!!window.XMLHttpRequest){ie = 7;}
else if(!!document.compatMode){ie = 6;}
else ie = 5;
}
}
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment