HTML5

浏览器和功能检测

Sascha p。Corti

 

如果您要构建一个网站,不仅希望其今天看上去非常漂亮,而且在很长时间内访问时都会觉得很耀眼。这意味着您的网站必须不仅可在当前的浏览器中工作,而且在未来的版本中也可正常工作。在这篇文章中我将介绍一些提示和最佳做法,可帮助您实现这一目标。

一个位的历史记录

如今,所有 Web 浏览器都天生具有一个共同的目标: 最新的说明书以最优方式呈现网页。

这始终没有这种情况。在过去,如浏览器供应商 raced 成为主导,最实施的功能的需求量很大,即使他们没有尚未实现标准化。当然,每个浏览器没有它自己的方式。下面是如何设置 CSS 中的透明度可变的一个示例。

Internet Explorer 之前版本 8 理解下面的 CSS:

    .transparent {      /* Internet Explorer < 9 */
        width: 100%;
        filter:alpha(opacity=50);
    }

虽然 Firefox 有其自己的属性:

    .transparent {
        /* Firefox < 0.9 */
        -moz-opacity:0.5;
    }

像那样 Safari:

    .transparent {
        /* Safari < 2 */
        -khtml-opacity: 0.5;
    }

现在,但是,在 CSS3,没有一种统一的方法来设置元素的透明度:

    .transparent {
        /* IE >= 9, Firefox >= 0.9, Safari >= 2, Chrome, Opera >= 9 */
        opacity: 0.5;
    }

尽管它可能看起来很好的浏览器转到支持非标准功能额外英里,但会使 Web 开发人员的使用寿命比需要,因为他不得不采取所有各种实现功能的考虑,将其添加到页面时。

一致的标记

请确保您的 Web 页将在所有浏览器中以最佳方式呈现的最佳方式是重点是某些支持所有当前版本的浏览器中的标记。 直到最近,这就是 HTML 4.01、 10 岁的孩子标准具有非常有限的功能。

如今,所有的浏览器都汇聚朝向功能丰富 HTML5 — 但是有许多汇总在常规术语,包括 HTML5 标记、 其 Api 如 DOM 级别 2 和 3,CSS3、 SVG 和 EcmaScript 262 下的新技术指标仍处于开发,因此可能会发生更改。 浏览器供应商正在不断添加支持新的 HTML5 功能,但在完全不同的变化。

Firefox 和 Opera 都是采用新的 HTML5 规范、 有时甚至是那些在早期开发和作出更改或的有安全问题通常非常快速。 尽管这可以是有趣为开发人员来测试新功能,它可能会导致断开之间由于的技术指标和它的实现之间的重大更改浏览器版本的 Web 页。 这是一种令人沮丧的体验,用户和开发人员。 这样的例子是 Firefox 4 禁用 Beta 7 和 8 之间的 Websockets 由于安全原因而来。

铬色,也很快就能采用新的 HTML5 标准是,最近 stirred HTML5 社区与公告它已放弃对流行 h.264 视频编解码器的 HTML5 <video> 支持 元素,而切换到的免版税 WEBM 标准。 尽管这可能是很好的开发人员目前支付 h.264 许可证,它增加了开发人员将不得不跟踪的为了尽可能支持多个浏览器的另一个选择。

Microsoft 较慢实施标准,但它但与紧密合作 W3C 生成测试套件,从而帮助最小化规范中所引起的多义性和技术的基础知识帮助供应商确保从事为了其浏览器呈现 HTML5 的方式。 若要查看此区域中的最新成果,有 Internet Explorer 10 平台预览,您可以找到这一看 IE 测试驱动器。 您还需要签出 HTML5labs Microsoft 原型早期、 不稳定规范从 Web 标准团体如 W3C 的位置。 请参阅部分中,"提高了互操作性,通过标准的支持,"Internet Explorer 9 》 为开发人员提供有关如何 Internet Explorer 9 支持各种 HTML5 规范今天的深入信息。

尽管如此,由于新的 HTML5 标准保持不活动目标,并且大多数 Internet 用户不使用各种 Web 浏览器的最新版本,提供服务的适当的标记是比以往任何时候都更重要。

浏览器检测

若要处理浏览器之间的差异的一种方法是使用浏览器检测。 要这样做的最常见方法是使用 JavaScript 查询的用户代理标头:

    <script type="text/javascript">
      if ( navigator.userAgent.indexOf("MSIE")>0 )
      {
        // Run custom code for Internet Explorer.
    }
    </script>

此方法的问题有两方面。 首先,它将捆绑多个假设在一个检查浏览器支持的功能。 单个错误的想法可以中断该站点。 因此作为开发人员,您需要跟踪确切的功能在特定的浏览器的每个版本支持。

第二个问题是此浏览器检查并不需要考虑的浏览器版本,并因此不是经得起未来考验。 即使它适用于当今的浏览器版本,在下一个版本可能不需要 — 或更糟糕的是,可能支持完全移除的 — — 一种解决办法浏览器检测用于添加到该站点。

因此,如果您有使用浏览器检测,请确保您考虑版本并仅使用这种方法检测旧版浏览器,如中所示图 1

图 1 检测旧版浏览器

    <script type="text/javascript">
      functiongetInternetExplorerVersion()
      // Returns the version of Internet Explorer or a -1 for other browsers.
    {
        var rv = -1;
        if(navigator.appName == 'Microsoft Internet Explorer')
        {
          var ua = navigator.userAgent;
          varre  = newRegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
          if(re.exec(ua) != null)
          rv = parseFloat( RegExp.$1 );
        }
        return rv;
      }
      functiononLoad()
      {
        var version = GetInternetExplorerVersion()
        if (version <= 7 && version > -1)
        {
          // Code to run in Internet Explorer 7 or earlier.
    }
      }
    </script>

MSDN 库页中,"检测浏览器更有效地,"具有的详细信息,并且您会发现一综合性文章如何使用导航对象和正则表达式来检测到各种浏览器,并在其确切版本 JavaScript 教程

从版本 5 开始,Internet Explorer 都有一种检测浏览器使用条件注释的唯一方法。 此语法扩展标准的 HTML 注释。 可以使用 CSS 使用这些条件的注释,来实现某些 Internet Explorer 特定的 CSS 规则要忽略其他浏览器。 在下面的示例中,"ie7.css"检测到 Internet Explorer 7 或更早版本时才加载:

    <!--[if lte IE 7]>
      <style TYPE="text/css">
        @import url(ie7.css);
      </style>
    <![endif]-->

有关如何使用条件注释的详细的信息可以中 MSDN 库页中,找到"条件的评论。"

给出所有的问题和限制浏览器检测,但是,让我们看一种替代方法。

特征检测

更好的解决方案来处理 Web 浏览器之间的差异是使用特征检测。 在使用之前您知道在各种浏览器中有不同的实现功能,您运行查找特定的对象、 方法、 属性或行为的可用性的一个小测试。 在大多数情况下这可通过试图创建新实例的功能有问题,并且正在执行的浏览器实例化返回 null 以外的任何值时,如果知道此功能。 如果没有,您可以通过测试的一种解决办法的可用性或功能的专有旧式实现后续。

比较浏览器和特征检测

让我们使用中的图表图 2,34 以帮助可视化两种方法在各种情况下的工作方式。

Possible Code Paths Through the Test Site
图 2 的可能的代码路径,通过测试站点

Results with Well-Known Browser Configurations
图 3 的结果与已知的浏览器配置

当面对众所周知的浏览器配置,这两种方法将工作,但浏览器检测具有固定的假设通过浏览器中,支持功能 A 和 B 功能而特征检测分别测试每个功能。

Unknown Browser Configuration
图 4 未知的浏览器配置

它是在面对令人感兴趣的未知的浏览器配置。 特征检测处理此就绪并找出在浏览器能够显示功能 A,但功能 b 需要回退代码 浏览器检测,另一方面,将选取基于浏览器的名称的路径,或选择的默认路径,因为所有的查询的浏览器版本组合都不匹配。 这两种方法,在此示例页将不会呈现正确,因为没有连接所有有效的代码段,即使该页实际上包含正确显示在此配置中未知的浏览器所必需的所有代码的代码路径。

功能检测示例

有两个非常重要的建议,以使用特征检测时,请记住:

  • 始终首先测试标准因为浏览器通常支持新的标准,以及传统的解决方法。
  • 总目标只与单个检查中的新功能,从而有效地最小化浏览器功能的假设。

现在我们来看几个示例的特征检测。

以下脚本创建两个代码路径。 它首先检查如果浏览器支持 window.addEventListener,并且如果不是,探测器旧式系统的可用性特征 window.attachEvent:

    <script type="text/javascript">
      if(window.addEventListener) {
        // Browser supports "addEventListener"
        window.addEventListener("load", myFunction, false);
      } else if(window.attachEvent) {
        // Browser supports "attachEvent"
        window.attachEvent("onload", myFunction);
      }
    </script>

另一个好方法是封装功能检测到一组然后可用于整个代码的函数。 下面是一种最佳做法来检测浏览器是否支持 HTML5 <canvas> 元素,如果是这样,可确保 canvas.getContext('2d') 方法是否也工作。 此函数只返回 true 或 false,使其很容易地重用。

    <script type="text/javascript">
      functionisCanvasSupported()
      {
        var elem = document.createElement('canvas'); 
        return!!(elem.getContext && elem.getContext('2d');
      }
    </script>

始终新使用特征检测时需要记住的一点创建元素或对象,因此您可以避免页面上的任何其他脚本已修改的元素或对象创建以来,它,这可能会导致随机或不稳定的结果的可能性。

特征检测也适用于直接的几个 HTML 元素如 HTML5 <video> <audio> 和 <canvas> 在窗体中的"后退"。浏览器显示从顶部的第一个受支持的子元素,并从视觉上隐藏下面的元素。

最简单的形式如下所示:

    <video src="video.mp4">
        Your browser doesn't support videos natively.
    </video>

支持 <video> 的浏览器 元素将显示视频的"video.mp4",而不浏览器将回退到使用所提供的文本。 但是回退还适用于视频的标记中的各种视频格式:

    <video>
        <source src="video.mp4" type="video/mp4" />
        <source src="video.webm" type="video/webm" />
        Your browser doen't suppport videos natively.
    </video>

在这种情况下,浏览器支持的 HTML5 <video> 将第一次尝试加载 mp4 视频。 如果它不支持这种格式,它将回退到 webm 编码视频。 应此格式不受支持或浏览器不应支持 <video> 在所有情况下,它将回退到该文本。

当然,它更有意义回退到插件的视频播放器的文本,而不是在浏览器不支持 HTML5 的情况下 <video> 在所有。 下面的示例使用 Silverlight 视频播放器:

    <video>
        <source src="video.mp4" type='video/mp4' />
        <source src="video.webm" type='video/webm' />
        <object type="application/x-silverlight-2">
            <param name="source" value="http://url/player.xap">
            <param name="initParams" value="m=http://url/video.mp4">
        </object>
        Download the video <a href="video.mp4">here</a>.
    </video>

非常相似的逻辑也在 CSS 中工作。 在 CSS 中,只被忽略无法识别的属性。 因此当您要添加多个实验性、 供应商为前缀的属性,使用"边框半径"下面所示,您只是可以在代码中包括所有变体。 这可能会感到有点不精确,但它易于使用,并获取有关这种情况下完成这项工作。 请注意它将您要包括第一次的供应商特定前缀的最佳做法和标准标记最后一次。

    <style type="text/css">
        .target
        {
            -moz-border-radius: 20px;
            -webkit-border-radius: 20px;
            border-radius: 20px;
        }
    </style>

特征检测到大有利因素是它还可利用您没有甚至考虑创建您的页面时,甚至与将来的浏览器版本由于它不依赖于任何假设哪些功能的浏览器支持的浏览器。

开发和测试功能检测

F12 开发人员工具 Internet Explorer 9 中非常适合于开发和跨多个浏览器中测试特征检测。 您可以使用它们要调试脚本步骤和更改浏览器的用户代理字符串,以及告诉使用呈现引擎的以前版本的 Internet Explorer**.**图 5、 6、 7 和 8 显示如何使用这些工具的一些示例。

Using Breakpoints while Debugging JavaScript in Internet Explorer 9
图 5 Internet Explorer 9 中的 JavaScript 在调试时使用断点

Running in “Document Mode: IE9 standards,” the bBrowser Uses the Modern addEventListener Method
图 6 中运行"文档模式: IE9 标准,"bBrowser 使用现代的 addEventListener 方法

Running in “Document Mode: IE7 standards,” the Debugger Falls Back to the Legacy attachEvent Method
图 7 中运行"文档模式: IE7 标准"调试器落回旧 attachEvent 方法

You Can Change the Internet Explorer User Agent String on the Fly and Even Add Your Own Strings, Including Those for Mobile Browsers
图 8 可以更改 Internet Explorer 用户代理字符串动态和甚至添加您自己的字符串,包括用于移动浏览器

在大型项目中的管理功能检测

创建复杂的 Web 项目时,创建和管理所有特征检测代码可以是单调乏味。 幸运的是,没有很好 JavaScript 库可用,可帮助在此工作,即 ModernizrjQuery

Modernizr 已获得大多数的 HTML5 和 CSS3 功能非常方便地使用您的代码中的内置检测。 它有非常广泛采用,并不断增强。 Modernizr 和 jQuery 附带 ASP。NET MVC 的工具。

看一看中的代码图 9,其中检测到浏览器的功能,而无需使用 Modernizr,然后在代码中显示 web 字体 图 10 Modernizr,它不会使用。

图 9,而无需 Modernizr

function(){
  var
    sheet, bool,
    head = docHead || docElement,
    style = document.createElement("style"),
    impl = document.implementation || { hasFeature: function()
      { return false; } };
    style.type = 'text/css';
    head.insertBefore(style, head.firstChild);
    sheet = style.sheet || style.styleSheet;
    var supportAtRule = impl.hasFeature('CSS2', '') ?
function(rule) {
        if (!(sheet && rule)) return false;
          var result = false;
          try {
            sheet.insertRule(rule, 0);
            result = (/src/i).test(sheet.cssRules[0].cssText);
            sheet.deleteRule(sheet.cssRules.length - 1);
          } catch(e) { }
          return result;
        } :
        function(rule) {
          if (!(sheet && rule)) return false;
          sheet.cssText = rule;
          return sheet.cssText.length !== 0 &&
            (/src/i).test(sheet.cssText) &&
            sheet.cssText
              .replace(/\r+|\n+/g, '')
              .indexOf(rule.split(' ')[0]) === 0;
        };
    bool = supportAtRule('@font-face { font-family: "font";
    src: url(data:,); }');
    head.removeChild(style);
    return bool;
  };

图 10 与 Modernizr

    <script type="text/javascript" src"modernizr.custom.89997.js"></script>
    <script type="text/javascript">
      if(Modernizr.fontface){
        // font-face is supported
      }
    </script>

添加缺少的功能支持

特征检测不会消除负担在随后与一种解决办法时经测试的浏览器不支持您需要的功能。 在早期 HTML5 视频示例中,使用作为后备的 Silverlight 是最直接的解决方案。 但什么有关 HTML5 的其他功能,如 <canvas> 新的语义标记,如 <nav>、 <section> 或 和 <article>,<aside>,或新的 <header> 和 <footer>?

越来越多的现成"回退"对于许多 HTML5 功能,称为填充和 polyfills,可以减轻该负担。 这些采用以下形式的 CSS 和 JavaScript 库或有时甚至在 Flash 或 Silverlight 的控件,您可以使用在项目中,将丢失的 HTML5 功能添加到浏览器,否则不支持它们的。

大致的想法是开发人员应该能够使用 HTML5 的 Api,开发和脚本可以创建的方法和应存在的对象。 开发这种经得起未来考验方式意味着像用户升级,不必更改代码和用户将干净地移动到更好的本机体验。

填充和 polyfills 之间的区别是填充程序只模仿功能和每个具有自己专有 API,而 polyfills 模拟的 HTML5 功能本身和其确切的 API。 因此,通常情况下,使用 polyfill 可以节省您不必采用专有 API 的麻烦。

HTML5 跨浏览器 Polyfills github 上的集合包含可用的填充和 polyfills 的不断增多。

Modernizr,例如,包括"HTML5Shim"的语义标记支持,但很容易地加载其他填充和 polyfills,如果 Modernizr 检测到不支持的功能。

动态添加支持

您可能会问自己,"将不会添加所有这些脚本库进行我的页面巨大和加载缓慢?"

嗯,这是真的使用这些支持库的许多可以添加到您的网站,巨大开销,以便动态地加载它们会在真正需要时才有其意义。 在这种垫片或 polyfill,最佳做法是仅当您已经检测到浏览器不支持本机 HTML5 功能时加载它们。

再次我们很幸运因为没有很好的库中支持完全这种情况下: yepnope.js

Yepnope 是异步资源加载器的 JavaScript 和 CSS 的工作方式以及将预加载从执行完全分离。 这意味着您有完全控制何时执行所需的资源,并且可以更改动态顺序。 Yepnope 将在 Modernizr 2 中,集成,但也可以自己上使用。 让我们来看看它的语法:

    <script type="text/javascript" src="yepnope.1.0.2-min.js"></script>
    <script type="text/javascript">
        yepnope({
            test : Modernizr.geolocation,
            yep  : 'normal.js',
            nope : ['polyfill.js', 'wrapper.js']
        });
    </script>

本示例从 Yepnope 页测试使用 HTML5 即使用 Modernizr 的浏览器的能力。如果支持,则将加载自己的代码 (normal.js); 否则,将加载自定义 polyfill (即 polyfill.js 和 wrapper.js 组成)。

最重要的几点总结了图 11

图 11 浏览器检测功能检测 Dos 和注意事项

  DO 不要
浏览器检测

请尝试完全避免。

为特定的浏览器的测试版本。

通过仅测试的浏览器名称,使将来的浏览器的假设。
特征检测 第一次测试标准。 假定下一个测试不相关的功能。

Resources:

了解有关在浏览器和功能检测:

Sascha p。 Corti的工作原理了解 Microsoft 瑞士作为开发推广人员侧重于 Microsoft 系统平台和开发人员工具和他向瑞士的开发人员社区介绍最新的趋势。他当前重点 Web 技术和 Windows Phone 7 平台。

他研究涉及计算机科学系以太网苏黎世和在大学的苏黎世的信息管理。

七年 Sascha 是一个软件开发人员和架构师,主要瑞士银行,他曾担任过多个美国的高科技公司,包括硅图形和 Microsoft 系统工程师和技术专家。

您可以阅读有关他最新的活动,在其网络日志上 http://techpreacher.corti.comhttps://blogs.msdn.com/swiss_dpe_team/ 或他遵照 Twitter @ TechPreacher

这要归功于以下的技术专家审阅这篇文章: 索军 GarretThomas Lewis