找回密码
 立即注册
首页 python Python-Web 查看内容
特征检测涉及确定浏览器是否支持某个代码块,并根据它是否(或不是)运行不同的代码,以便浏览器总是能够在某些浏览器中提供工作体验而不是崩溃/错误。本文详细介绍了如何编写自己的简单特征检测,如何使用库来加速实现,以及如特征检测的本​​机特性@supports


先决条件:
熟悉核心HTMLCSSJavaScript语言; 了解跨浏览器测试的高级原则
目的:
了解特征检测的概念是什么,并能够在CSS和JavaScript中实现合适的解决方案。


特征检测部分的概念


特征检测背后的想法是,你可以运行测试,以确定在当前浏览器功能是否支持,并有条件地运行代码以提供可接受的经验都在浏览器支持的功能和浏览器是。如果您不这样做,那些不支持您在代码中使用的功能的浏览器将无法正确显示您的网站,只会失败,从而产生糟糕的用户体验。


让我们回顾一下我们处理常见JavaScript问题时所涉及的示例- Geolocation API   (公开运行Web浏览器的设备的可用位置数据)有一个主要入口点供其使用,一个geolocation属性可用于全局导航器对象。因此,您可以使用以下内容检测浏览器是否支持地理位置:
if ("geolocation" in navigator) {
  navigator.geolocation.getCurrentPosition(function(position) {
    // show the location on a map, perhaps using the Google Maps API
  });
} else {
  // Give the user a choice of static maps instead perhaps
}
然而,使用已建立的特征检测库可能更好,而不是一直编写自己的特征检测库。Modernizr是功能检测测试的行业标准,稍后我们将对此进行介绍。


在我们继续之前,我们想先说一件事 - 不要将功能检测与浏览器嗅探混淆(检测特定浏览器访问网站的内容) - 这是一种可怕的做法,应该不惜一切代价加以劝阻。


编写自己的功能检测测试


在本节中,我们将介绍如何在CSS和JavaScript中实现您自己的功能检测测试。


CSS


您可以通过在JavaScript中测试element.style.property(例如paragraph.style.transform)的存在来编写CSS功能的测试。


一个典型的例子可能是在浏览器中测试Flexbox支持; 对于支持最新Flexbox规范的浏览器,我们可以使用灵活且强大的Flex布局。对于那些没有的浏览器,我们可以使用一个工作正常的浮动布局,虽然它稍微脆弱和黑客,而不是看起来很酷。


让我们实现一些可以证明这一点的东西,尽管我们现在仍然保持简单。


  • 通过使我们的本地副本开始css-feature-detect.htmlflex-layout.cssfloat-layout-css,和basic-styling.css文件。将它们保存在新目录中。
  • 我们也将HTML5 Shiv添加到我们的示例中,以便HTML5语义元素在旧版本的IE中正确地设置样式。下载最新版本(请参阅手动安装),解压缩ZIP文件,将文件html5shiv-printshiv.min.js和html5shiv.min.js文件复制到示例目录中,并通过将以下内容放在<title>元素下链接到其中一个文件:

<script src="html5shiv.min.js"></script>
看看你的示例CSS文件 - 你会看到它  basic-styling.css处理我们想要给每个浏览器的所有样式,而另外两个CSS文件包含我们想要根据它们的支持级别选择性地应用于浏览器的CSS。您可以通过手动更改第二个<link>元素引用的CSS文件来查看这两个文件的不同效果,但是让我们实现一些JavaScript以根据需要自动交换它们。


首先,删除第二个<link>元素href属性的内容。我们稍后将动态填写此内容。


接下来,<script></script>在您的身体底部添加一个元素(在结束</body>标记之前)。


给它以下内容:
var conditional = document.querySelector('.conditional');
var testElem = document.createElement('div');
if (testElem.style.flex !== undefined && testElem.style.flexFlow !== undefined) {
  conditional.setAttribute('href', 'flex-layout.css');
} else {
  conditional.setAttribute('href', 'float-layout.css');
}
这里我们抓住对第二个<link>元素的引用,并<div>在我们的测试中创建一个元素。在我们的条件语句中,我们测试浏览器中存在flexflex-flow属性。请注意存储在HTMLElement.style对象内的那些属性的JavaScript表示如何使用较低的驼峰大小写而不是连字符来分隔单词。


注意:如果您无法使用此功能,可以将其与我们的css-feature-detect-finished.html代码进行比较(另请参阅实时版本)。


当你保存所有内容并试用你的例子时,如果浏览器支持现代的flexbox,你应该看到应用于页面的flexbox布局,如果没有,你应该看到浮动布局。


注意:对于轻微的功能检测问题,这种方法通常是过度的 - 您可以经常使用多个供应商前缀和回退属性,如CSS回退行为处理CSS前缀中所述


@supports最近,CSS引入了自己的本机特征检测机制 - @supports规则。这与媒体查询的工作方式类似(另请参阅响应式设计问题) - 除了根据分辨率,屏幕宽度或宽高比等媒体功能选择性地应用CSS,它根据CSS功能是否有选择性地应用CSS。支持的。


例如,我们可以重写我们之前使用的示例@supports- 请参阅supports-feature-detect.htmlsupports-styling.css。如果你看后者,你会看到几个@supports块,例如:

@supports (flex-flow: row) and (flex: 1) {

  main {
    display: flex;
  }

  main div {
    padding-right: 4%;
    flex: 1;
  }

  main div:last-child {
    padding-right: 0;
  }

}
仅当当前浏览器同时支持flex-flow: rowflex: 1声明时,此规则块才应用CSS规则。要使每个条件起作用,您需要包含完整的声明(不仅仅是属性名称),并且不要在末尾包含分号。


@supports还有OR和NOT逻辑可用 - 如果flexbox属性不可用,则另一个块应用浮动布局:
@supports not (flex-flow: row) and (flex: 1) {

  /* rules in here */

}
这可能看起来比前面的示例更方便 - 我们可以在CSS中执行所有功能检测,不需要JavaScript,并且我们可以处理单个CSS文件中的所有逻辑,从而减少HTTP请求。这里的问题是浏览器支持 - @supports在IE中根本不支持,并且仅在最新版本的Safari / iOS WebKit(9 + / 9.2 +)中受支持,而JavaScript版本应该在更旧的浏览器中工作(可能回到IE8)或者9,虽然IE的旧版本会有其他问题,例如不支持Document.querySelector,并且有一个混乱的盒子模型)。


JavaScript


我们之前已经看过一个JavaScript特征检测测试的例子。通常,此类测试通过以下常见模式之一完成:


JavaScript特征检测技术摘要
[td]
特征检测类型
说明
如果成员在对象中检查其父对象中是否存在某个方法或属性(通常是使用API​​或其他要检测的功能的入口点)。
if("geolocation" in navigator) { ... }
元素属性在内存中创建一个元素,Document.createElement()然后检查它是否存在属性。显示的示例是一种检测HTML5 Canvas支持的方法。function supports_canvas() {
return !!document.createElement('canvas').getContext;
}

if(supports_canvas()) { ... }
元素返回值的方法使用内存中的元素创建Document.createElement(),然后检查是否存在方法。如果是,请检查它返回的值。请参阅Dive Into HTML5视频格式检测测试。
元素属性保留价值使用创建元素Document.createElement(),将属性设置为某个值,然后检查该值是否保留。请参阅Dive into HTML5 <input>类型检测测试。


注意NOT上面example(!!)中的double 是一种强制返回值成为“正确”布尔值的方法,而不是可能使结果偏斜的Truthy / Falsy值。


潜入HTML5检测HTML5功能页面有除了上面列出的多了很多有用的功能检测试验,你通常可以通过搜索“检测为您-功能支持这里的”您最喜爱的发现对于大多数事情特征检测试验搜索引擎。请记住,虽然已知某些功能无法检测到 - 请参阅Modernizr的Undetectables列表。


matchMedia我们也想Window.matchMedia在这一点上提到JavaScript功能。这是一个允许您在JavaScript中运行媒体查询测试的属性。它看起来像这样:

if (window.matchMedia("(max-width: 480px)").matches) {
  // run JavaScript in here. 
}

例如,我们的Snapshot演示使用它来有选择地应用Brick JavaScript库并使用它来处理UI布局,但仅适用于小屏幕布局(480px宽或更小)。media如果页面宽度为480px或更小,我们首先使用该属性仅将Brick CSS应用于页面:
<link href="dist/brick.css" type="text/css" rel="stylesheet" media="all and (max-width: 480px)">

然后我们matchMedia()在JavaScript中多次使用,如果我们在小屏幕布局上运行Brick导航功能(在更宽的屏幕布局中,一切都可以一次看到,所以我们不需要在不同的视图之间导航)。
if (window.matchMedia("(max-width: 480px)").matches) {
  deck.shuffleTo(1);  
}

使用Modernizr实现特征检测


可以使用上面详述的技术实现您自己的特征检测测试。不过,您可以使用专用的功能检测库,因为它使事情变得更容易。所有功能检测库的母亲都是Modernizr,它可以检测到您需要的所有内容。我们来看看如何使用它。


当您尝试使用Modernizr时,您也可以使用开发构建,其中包括所有可能的特征检测测试。立即下载:


  • 单击Development build链接。
  • 单击出现的页面中的粉红色Build按钮。
  • 单击出现的对话框中的顶部下载链接。

将它保存在合理的位置,就像您在本文中创建其他示例的目录一样。


在生产中使用Modernizr时,您可以转到已访问过的“ 下载”页面,然后单击加号按钮,仅显示您需要检测的功能。然后,当您单击“ 构建”按钮时,您将下载仅包含这些功能检测的自定义构建,从而使文件大小更小。

CSS


让我们来看看Modernizr如何在有选择地应用CSS方面发挥作用。


首先,复制supports-feature-detect.htmlsupports-styling.css。将它们保存为modernizr-css.html和modernizr-css.css。

更新<link>HTML中的元素,使其指向正确的CSS文件(您还应该将<title>元素更新为更合适的元素!):

<link href="modernizr-css.css" rel="stylesheet">

在此<link>元素上方,添加一个<script>元素以将Modernizr库应用于页面,如下所示。这需要在任何可能使用它的CSS(或JavaScript)之前应用于页面。
<script src="modernizr-custom.js"></script>

现在编辑您的开始<html>标记,使它看起来像这样:
<html class="no-js">

此时,尝试加载您的页面,您将了解Modernizr如何为CSS功能工作。如果您查看浏览器开发人员工具的DOM检查器,您会看到Modernizr已更新您的<html> class值,如下所示:
<html class="js no-htmlimports sizes flash transferables applicationcache blobconstructor
blob-constructor cookies cors ...AND LOADS MORE VALUES!>

它现在包含大量类,表明不同技术功能的支持状态。例如,如果浏览器根本不支持flexbox,<html>则会给出类名no-flexbox。如果它支持现代的flexbox,它将获得一个类名flexbox。如果您搜索班级列表,您还会看到与Flexbox相关的其他内容,例如:

  • flexboxlegacy 对于旧的flexbox规范(2009年)。
  • flexboxtweener 对于IE10支持的2011 inbetween语法
  • flexwrap对于flex-wrap属性,在某些实现中不存在。




注意:您可以找到所有类名的含义列表 - 请参阅Modernizr检测到的功能


继续,让我们更新我们的CSS以使用Modernizr而不是@supports。进入modernizr-css.css,并用@supports以下内容替换这两个块:
/* Properties for browsers with modern flexbox */

.flexbox main {
  display: flex;
}

.flexbox main div {
  padding-right: 4%;
  flex: 1;
}

.flexbox main div:last-child {
  padding-right: 0;
}

/* Fallbacks for browsers that don't support modern flexbox */

.no-flexbox main div {
  width: 22%;
  float: left;
  padding-right: 4%;
}

.no-flexbox main div:last-child {
  padding-right: 0;
}

.no-flexbox footer {
  clear: left;
}
那怎么办?由于所有这些类名都已放在<html>元素上,因此您可以使用特定的后代选择器来定位支持或不支持功能的浏览器。所以这里我们只将顶级规则应用于支持flexbox的浏览器,而将底层规则仅应用于不支持(no-flexbox)的浏览器。


注意:请记住,所有Modernizr的HTML和JavaScript功能测试也会在这些类名中报告,因此,如果需要,您可以根据浏览器是否支持HTML或JavaScript功能来选择性地应用CSS。


注意:如果您无法使用此功能,请根据我们的文件modernizr-css.htmlmodernizr-css.css文件检查您的代码(请参阅此版本也可以直播)。


JavaScript


Modernizr同样也为实现JavaScript功能检测做好了充分的准备。它通过使全局Modernizr对象可用于其应用的页面来实现,其中包含该功能的结果检测为true/ falseproperties。


例如,modernizr-css.html在浏览器中加载我们的示例,然后尝试转到您的JavaScript控制台并输入Modernizr.其中一些类名(它们在这里也是相同的)。例如:
Modernizr.flexbox
Modernizr.websqldatabase
Modernizr.xhr2
Modernizr.fetch
控制台将返回true/ false值以指示您的浏览器是否支持这些功能。


让我们看一个示例来说明如何使用这些属性。


  • 首先,制作modernizr-js.html示例文件的本地副本。
  • 使用<script>元素将Modernizr库附加到HTML ,就像我们在之前的演示中所做的那样。将它放在现有<script>元素上方,该元素将Google Maps API附加到页面。
  • 接下来,使用有效的Google Maps API密钥填充YOUR-API-KEY第二个<script>元素(就像现在一样)中的占位符文本。要获取密钥,请登录Google帐户,转到“ 获取密钥/身份验证”页面,然后点击蓝色的“ 获取密钥”按钮并按照说明操作。
  • 最后,<script>在HTML主体的底部添加另一个元素(在</body>标记之前),并将以下脚本放在标记内:


if (Modernizr.geolocation) {

  navigator.geolocation.getCurrentPosition(function(position) {

    var latlng = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);
    var myOptions = {
      zoom: 8,
      center: latlng,
      mapTypeId: google.maps.MapTypeId.TERRAIN,
      disableDefaultUI: true
    }
    var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
  });

} else {
  var para = document.createElement('p');
  para.textContent = 'Argh, no geolocation!';
  document.body.appendChild(para);
}
试试你的例子吧!在这里,我们使用Modernizr.geolocation测试来检查当前浏览器是否支持地理定位。如果是,我们会运行一些代码来获取您设备的当前位置,并将其绘制在Google地图上。




分享至 : QQ空间
收藏
您需要登录后才可以回帖 登录 | 立即注册