使用CSS能力/特性检测来检测IE版本

100

IE10+不再支持使用浏览器检测标签来识别浏览器。

为了检测IE10,我使用JavaScript和一种能力测试技术来检测是否定义了某些带有ms前缀的样式,例如msTouchActionmsWrapFlow

我想对IE11做同样的事情,但我假设所有的IE10样式在IE11中也会得到支持。有人可以帮我识别只能用于IE11的样式或能力,以便将两者区分开来吗?

额外信息

  • 我不想使用用户代理类型检测,因为它很容易出错,而且可以更改,另外我认为我读过IE11有意试图隐藏它是Internet Explorer的事实。
  • 关于如何进行IE10能力测试的示例,我使用了这个JsFiddle(不是我的),作为我的测试基础。
  • 同时,我预计会有很多答案是“这是一个坏主意……”。我之所以需要这样做,是因为IE10声称支持某些功能,但实现非常糟糕,我想能够区分IE10和IE11+,以便在未来使用基于能力的检测方法。
  • 这个测试与一个Modernizr测试结合使用,它将简单地使一些功能“回退”到不太显眼的行为。我们并不谈论关键功能。

我已经在使用Modernizr了,但它在这里没有帮助。


3
为什么需要知道用户使用的浏览器?特性检测/ CSS前缀 / CSS条件语句不足以满足吗? - David-SkyMesh
4
我忘了提到我们需要检测浏览器的原因,这是能力测试无法解决的。我们面临的问题之一是IE10会声明支持某项功能,但实际表现并不好。 - dano
2
@David-SkyMesh - 不好意思,这还不够。虽然我希望它足够了,但事实并非如此。 - dano
1
@Evildonald,你没有回答为什么需要知道这个问题的具体原因。这可能是一个XY问题(即:当我们可以回答不同的问题Y - 如何兼容更多浏览器包括IE11,以完成任务Z时,你正在寻求帮助解决X - 检测IE11)。 - David-SkyMesh
1
我有一个可以检测浏览器版本的 .js 文件,但它却将 ie11 识别为 firefox。这是怎么回事,ie 开发者! - Daniel Cheung
显示剩余3条评论
18个回答

2
你应该使用Modernizr,它会向body标签添加一个类。
此外:
function getIeVersion()
{
  var rv = -1;
  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 );
  }
  else if (navigator.appName == 'Netscape')
  {
    var ua = navigator.userAgent;
    var re  = new RegExp("Trident/.*rv:([0-9]{1,}[\.0-9]{0,})");
    if (re.exec(ua) != null)
      rv = parseFloat( RegExp.$1 );
  }
  return rv;
}

请注意,IE11仍处于预览阶段,用户代理可能会在发布之前更改。
目前IE 11的用户代理字符串为:
Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv 11.0) like Gecko

这意味着您可以简单地测试11.xx版本。
var isIE11 = !!navigator.userAgent.match(/Trident.*rv 11\./)

谢谢Neo,但我已经在我的body标签中添加了一个类,并且正在使用Modernizr。我想要一种区分IE10和IE11的方法,而不使用不可靠的用户代理。 - dano
在rv 11中缺少冒号。var isIE11 = !!navigator.userAgent.match(/Trident.*rv:11./) - T.CK

2
检测IE及其版本实际上非常容易,至少非常直观:
var uA = navigator.userAgent;
var browser = null;
var ieVersion = null;

if (uA.indexOf('MSIE 6') >= 0) {
    browser = 'IE';
    ieVersion = 6;
}
if (uA.indexOf('MSIE 7') >= 0) {
    browser = 'IE';
    ieVersion = 7;
}
if (document.documentMode) { // as of IE8
    browser = 'IE';
    ieVersion = document.documentMode;
}

这样,你也可以在兼容模式/视图中捕获高版本的IE。接下来,就是分配条件类的问题:

var htmlTag = document.documentElement;
if (browser == 'IE' && ieVersion <= 11)
    htmlTag.className += ' ie11-';

2
如果您正在使用Modernizr - 您可以轻松区分IE10和IE11。
IE10不支持pointer-events属性。IE11支持。(caniuse)
现在,基于Modernizr插入的类,您可以拥有以下CSS:
.class
{ 
   /* for IE11 */
}

.no-pointerevents .class
{ 
   /* for IE10 */
}

2
也许Layout Engine v0.7.0是你情况下的好方案。它使用浏览器特性检测,不仅可以检测IE11和IE10,还可以检测IE9、IE8和IE7。它还可以检测其他流行的浏览器,包括一些移动浏览器。它向html标签添加一个类,易于使用,在一些深度测试中表现良好。 http://mattstow.com/layout-engine.html

2
您可以尝试这个方法:
if(document.documentMode) {
  document.documentElement.className+=' ie'+document.documentMode;
}

2

您可以使用 JavaScript 并在 HTML 中添加类来维护 条件注释 的标准:

  var ua = navigator.userAgent,
      doc = document.documentElement;

  if ((ua.match(/MSIE 10.0/i))) {
    doc.className = doc.className + " ie10";

  } else if((ua.match(/rv:11.0/i))){
    doc.className = doc.className + " ie11";
  }

或者使用类似bowser的库:

https://github.com/ded/bowser

或者使用Modernizr进行特性检测:

http://modernizr.com/


2

我在IE11中使用Gravity表单(WordPress)时遇到了同样的问题。 表单的列样式“display:inline-grid”破坏了布局; 应用上面的答案解决了差异!

最初的回答:

@media all and (-ms-high-contrast:none){
  *::-ms-backdrop, .gfmc-column { display: inline-block;} /* IE11 */
}

1
步骤回溯:你为什么要检测“Internet Explorer”而不是“我的网站需要做X,这个浏览器是否支持该功能?如果是,那么是好的浏览器。如果不支持,则应该警告用户”。
你应该访问http://modernizr.com/,而不是继续你正在做的事情。

谢谢提供另一种解决方案,但我已经在使用Modernizr了,而IE10对它的能力进行了错误的描述。 - dano
4
我假设你知道具体是哪个浏览器,已向Modernizr提交问题报告,以便他们可以添加更多的检查来支持该浏览器?如果没有,请尽快提交。如果你发现某些问题会影响成千上万的开发人员,将它报告给负责 shim 的人是唯一正确的做法。 - Mike 'Pomax' Kamermans
7
对于我们编写面向用户的代码的人来说,通常需要立即得到答案,而不是在第三方库中提交错误并进行修补。也就是说,你希望他们改进Modernizr是很好的,但它不适用于这里。 - Dean J
1
我认为检测真实的浏览器本身是一个合理的目标。 - jds
@DeanJ 当然,对于那些问题,其他人也会提供答案。这并不意味着获得像这样告诉你要考虑自己在做什么的回复就不重要了。此外,在回复时,帖子还没有进行编辑,并且没有提到“我需要它立即工作”,因此我没有理由认为他们不想要现实检查。 - Mike 'Pomax' Kamermans

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接