使用 Modernizr 检测 IE 的正确方法?

Posted

技术标签:

【中文标题】使用 Modernizr 检测 IE 的正确方法?【英文标题】:Correct way to use Modernizr to detect IE? 【发布时间】:2012-11-08 19:42:33 【问题描述】:

我想使用 Modernizr JS 库来检测某些浏览器属性以确定显示或不显示的内容。

我有一个名为Pano2VR 的应用程序,它同时输出 html5 和 SWF。我需要 ios 设备用户的 HTML5。

但是,IE 根本不呈现这个“HTML5”输出。似乎他们的输出使用了 CSS3 3D 转换和 WebGL,其中一种或多种在 IE9 中显然不受支持。

因此,对于那些用户,我需要显示 Flash 版本。我打算使用 IFRAME 并通过 Modernizr 脚本或文档传递 SRC。根据浏览器写出正确的 IFRAME 代码。

所有这些都导致我如何使用 Modernizr 来检测简单的 IE 或不检测 IE?或者检测 CSS 3d 变换?

或者有其他方法吗?

【问题讨论】:

【参考方案1】:

Modernizr 本身并不会检测浏览器,它会检测存在哪些特性和功能,这就是它尝试做的全部内容。

您可以尝试像这样挂钩一个简单的检测脚本,然后使用它来做出选择。我还包括了版本检测,以防万一。如果您只想检查任何版本的 IE,您只需查找值为“MSIE”的 navigator.userAgent。

var BrowserDetect = 
        init: function () 
            this.browser = this.searchString(this.dataBrowser) || "Other";
            this.version = this.searchVersion(navigator.userAgent) || this.searchVersion(navigator.appVersion) || "Unknown";
        ,
        searchString: function (data) 
            for (var i = 0; i < data.length; i++) 
                var dataString = data[i].string;
                this.versionSearchString = data[i].subString;

                if (dataString.indexOf(data[i].subString) !== -1) 
                    return data[i].identity;
                
            
        ,
        searchVersion: function (dataString) 
            var index = dataString.indexOf(this.versionSearchString);
            if (index === -1) 
                return;
            

            var rv = dataString.indexOf("rv:");
            if (this.versionSearchString === "Trident" && rv !== -1) 
                return parseFloat(dataString.substring(rv + 3));
             else 
                return parseFloat(dataString.substring(index + this.versionSearchString.length + 1));
            
        ,

        dataBrowser: [
            string: navigator.userAgent, subString: "Edge", identity: "MS Edge",
            string: navigator.userAgent, subString: "MSIE", identity: "Explorer",
            string: navigator.userAgent, subString: "Trident", identity: "Explorer",
            string: navigator.userAgent, subString: "Firefox", identity: "Firefox",
            string: navigator.userAgent, subString: "Opera", identity: "Opera",  
            string: navigator.userAgent, subString: "OPR", identity: "Opera",  

            string: navigator.userAgent, subString: "Chrome", identity: "Chrome", 
            string: navigator.userAgent, subString: "Safari", identity: "Safari"       
        ]
    ;
    
    BrowserDetect.init();
    document.write("You are using <b>" + BrowserDetect.browser + "</b> with version <b>" + BrowserDetect.version + "</b>");

然后您可以简单地检查:

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

【讨论】:

谢谢。我最终追查到问题是他们的文件需要 webgl 支持。因此,我可以使用 Modernizer 进行测试,并对另一个代码块执行 document.write。但这是浏览器检测的绝佳解决方案。再次感谢。 要记住的一点:UA 字符串是完全可由用户配置的。所以检查 UA 字符串并不是检查浏览器的一致方式。 developer.mozilla.org/en-US/docs/DOM/window.navigator.userAgent 在“备注”部分:Browser identification based on detecting the user agent string is unreliable and is not recommended, as the user agent string is user configurable. 是的,但是有多少百分比的用户使用修改/欺骗/不正确的 UA 字符串浏览网页?您希望花费多少工程时间来确保少数人在您的网站上获得最佳体验?通过 UA 字符串进行浏览器嗅探是一种实用且理智的方法。 @Wintamute,完全同意。厌倦“特征检测是邪恶的”那种讲座。我们在做工程,而不是追求艺术 一般的假设是,如果有人修改了他们的 UA 字符串,那么他们就知道自己在做什么,并且可以处理后果。事实上,这正是 UA 字符串存在的目的——向服务器声明浏览器版本。如果客户想对此撒谎,那么,这就是生活!当然,在未经用户同意的情况下更改字符串的可能性很小,但实际上这不是一个真正的问题 - 嘿,我们应该喂用户并抚摸他们的背部吗?【参考方案2】:

您可以使用Modernizr 通过检查 SVG SMIL 动画支持来简单地检测 IE 或非 IE。

如果您在 Modernizr 设置中包含 SMIL 功能检测,则可以使用简单的 CSS 方法,并定位 Modernizr 适用的 .no-smilhtml 元素:

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

或者,您可以将 Modernizr 与简单的 javascript 方法一起使用,如下所示:

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

请记住,IE/Edge 有朝一日可能会支持 SMIL,但目前还没有这样做的计划。

作为参考,这里是 SMIL 兼容性图表的链接caniuse.com。

【讨论】:

最佳答案 imo。这么简单 虽然这确实有效,但它现在有效。特征检测和 Modernizr 的全部意义在于您不必担心明天会发生什么。如果 Edge 明天通过 smil 支持更新,您的代码将不再有效,您甚至可能都不知道。 还有no plans for SMIL support in Edge。 这看起来很简单,但显然Edge now supports SMIL。【参考方案3】:

检测 CSS 3D 变换

Modernizr can detect CSS 3D transforms,是的。 Modernizr.csstransforms3d 的真实性会告诉你浏览器是否支持它们。

上面的链接让您可以选择要在 Modernizr 构建中包含哪些测试,并且您正在寻找的选项在那里可用。


专门检测IE

或者,正如 user356990 回答的那样,如果您只搜索 IE 和 IE,则可以使用条件 cmets。您可以使用 HTML5 Boilerplate 的 &lt;html&gt; 条件 cmets 技巧来分配一个类,而不是创建一个全局变量:

<!--[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]-->

如果你已经初始化了 jQuery,你可以通过$('html').hasClass('lt-ie9') 来检查。如果您需要检查您所在的 IE 版本以便有条件地加载 jQuery 1.x 或 2.x,您可以执行以下操作:

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;
());

注意IE 条件 cmets 仅支持 IE9(包括 IE9)。从 IE10 开始,微软鼓励使用功能检测而不是浏览器检测。


无论您选择哪种方法,都可以使用

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

当然,不要从字面上理解||

【讨论】:

我个人总是尝试做基于特征的检测而不是浏览器检测 @Chris 对你有好处,这里也一样吗?我……不认为你真的读过我的回答。 Yours 是第一个实际建议使用功能检测的答案,因此认为如果他们阅读评论可能会对其他人有所帮助 @Chris 哦,对不起。我以为你在谴责我参加 IE 测试。【参考方案4】:

如果您正在寻找 html5 样板的 JS 版本(结合使用特征检测和 UA 嗅探):

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

【讨论】:

【参考方案5】:

好吧,在对这个主题进行了更多研究之后,我最终使用了以下针对 IE 10+ 的解决方案。 由于 IE10&11 是唯一支持 -ms-high-contrast 媒体查询的浏览器,因此无需任何 JS,这是一个不错的选择:

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

完美运行。

【讨论】:

【参考方案6】:

CSS 技巧对 IE 11 有很好的解决方案:

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

.NET 和 Trident/7.0 是 IE 独有的,因此可用于检测 IE 版本 11。

然后代码将用户代理字符串添加到具有属性“data-useragent”的 html 标记中,因此可以专门针对 IE 11...

【讨论】:

【参考方案7】:

我同意我们应该测试功能,但是很难找到一个简单的答案来回答“'现代浏览器'支持哪些功能,而不是'旧浏览器'?”

所以我启动了一堆浏览器并直接检查了 Modernizer。 我添加了一些我绝对需要的功能,然后我添加了“inputtypes.color”,因为它似乎涵盖了我关心的所有主要浏览器:Chrome、Firefox、Opera、Edge……而不是 IE11。现在我可以温和地建议用户使用 Chrome/Opera/Firefox/Edge 会更好。

这就是我使用的 - 您可以编辑要针对您的特定情况进行测试的事物列表。 如果缺少任何功能,则返回 false。

/**
 * Check browser capabilities.
 */
public CheckBrowser(): boolean

    let tests = ["csstransforms3d", "canvas", "flexbox", "webgl", "inputtypes.color"];

    // Lets see what each browser can do and compare...
    //console.log("Modernizr", Modernizr);

    for (let i = 0; i < tests.length; i++)
    
        // if you don't test for nested properties then you can just use
        // "if (!Modernizr[tests[i]])" instead
        if (!ObjectUtils.GetProperty(Modernizr, tests[i]))
        
            console.error("Browser Capability missing: " + tests[i]);
            return false;
        
    

    return true;

这里是“inputtypes.color”所需的 GetProperty 方法。

/**
 * Get a property value from the target object specified by name.
 * 
 * The property name may be a nested property, e.g. "Contact.Address.Code".
 * 
 * Returns undefined if a property is undefined (an existing property could be null).
 * If the property exists and has the value undefined then good luck with that.
 */
public static GetProperty(target: any, propertyName: string): any

    if (!(target && propertyName))
    
        return undefined;
    

    var o = target;

    propertyName = propertyName.replace(/\[(\w+)\]/g, ".$1");
    propertyName = propertyName.replace(/^\./, "");

    var a = propertyName.split(".");

    while (a.length)
    
        var n = a.shift();

        if (n in o)
        
            o = o[n];

            if (o == null)
            
                return undefined;
            
        
        else
        
            return undefined;
        
    

    return o;

【讨论】:

【参考方案8】:

我需要检测 IE 和大多数其他东西,我不想依赖 UA 字符串。我发现将 es6number 与 Modernizr 一起使用正是我想要的。我不太担心这种变化,因为我不希望 IE 支持 ES6 Number。所以现在我知道任何版本的 IE 与 Edge/Chrome/Firefox/Opera/Safari 之间的区别了。

更多详情:http://caniuse.com/#feat=es6-number

请注意,我并不真正关心 Opera Mini 的误报。你可能是。

【讨论】:

【参考方案9】:

您可以使用&lt; !-- [if IE] &gt; hack 设置一个全局 js 变量,然后在您的普通 js 代码中进行测试。有点难看,但对我来说效果很好。

【讨论】:

Internet Explorer >=10 不再支持条件 cmets。

以上是关于使用 Modernizr 检测 IE 的正确方法?的主要内容,如果未能解决你的问题,请参考以下文章

html 5 样板或 initializr 上的 IE 条件不适用于 Modernizr?

一种检测mouseenter vs touch点击的方法?使用Modernizr怎么样?

Modernizr.load 在 IE7/IE8 中不提供输入和文本区域占位符支持

HTML5中Modernizr类库是做啥用的?具体怎么使用?

如果您不使用特征检测,真的需要 Modernizr 吗?

使用 Javascript(并且没有modernizr)检测 CSS 转换?