随着HTML5和CSS3的飞速发展,愈来愈多语义化的标签和炫酷的特性被应用到web应用开发中来,各大浏览器厂商纷纷开始支持这些新特性,web开发人员也都兴趣十足地试用这些新特性开发出更绚丽有趣的应用,可是各大浏览器对这些新特性良莠不齐地支持(尤为是使人头疼的IE)所带来的版本兼容性问题始终都是萦绕在开发人员心头的噩梦。传统的使用习惯使得咱们很难摒弃老版本浏览器,开发人员只能选择使人厌烦的手工测试,测试,再测试。javascript
为了解决这一难题,Modernizr应运而生了。它的名字听起来有点像Modernize, 确实,该名字起源于使得开发体验可以更现代化的目的,但它并不是试图使旧的浏览器现代化,也就是使它支持这些新特性(尽管你确实能够经过添加shim/polyfill脚原本让浏览器支持某些不支持的新特性,后面会介绍)。html
Modernizr是一个检测浏览器对HTML5和CSS3特性支持的开源的js库,著名的HTML5/CSS3浏览器兼容性网站FindmeByIP就是基于该框架实现的。咱们可以利用它来检测浏览器是否支持某种新特性,甚至能够额外加载script脚本,知足你根据不一样的状况动态加载不一样的js文件来减小下载量提升性能的需求。java
Modernizr提供development和production两个版本,development版本包含了对全部HTML5和CSS3新特性的检测,适用于学习和测试,对于刚开始使用Modernizr的新手来讲,bella建议你使用这个版本。当你熟悉了Modernizr的工做原理后,你就可使用production这个自定义版本,你能够只下载任意数量的你须要检测的特性从而大大减少下载量,这在某种程度上是能小幅提升你程序的性能的。你能够在http://modernizr.com/download/上下载这两个版本,点击该页面上的development version连接,就能够下载development版,或者,你已经看到了以下的特性显示页面git
你能够勾选任意你想要测试的HTML5或CSS3特性,可是默认情形下,Extra分类将会选中以下三项:github
a) HTML5 Shiv v3.6:它添加了一个脚本— HTML5 shim 它会迫使迫使 IE6-8 正确地设计并打印 HTML5 元素。若是你打算使用新的 HTML5 语义标签,例如 <header>、<footer>、 <nav>、<section>、<article>等等,那么你须要选这个选项。web
b) Modernizr.load(yepnope.js):它添加了一个不包含在 development 版本中的可选择的脚本加载器。它增长了3KB 的下载量,因此若是你不须要它,你能够放弃选择它。chrome
c) Add CSS Classes: 它将 Modernizr 类添加到开始的标签。若是你想检测对 CSS3 功能支持,那么你必须选择这个选项。浏览器
Modernizr的使用方法很简单,当你下载了如development版本后只需在页面中引入js库文件便可,如:框架
1 |
< script type = "”text/javascript”" src = "“js/modernizr.js”" ></ script > |
添加完Modernizr引用后,js程序运行的时候它会在html元素上添加一批CSS的class名称,这些class名称标记当前浏览器支持哪些特性和不支持哪些特性,若是支持会显示相应的特性名,不支持的话就显示no-特性名。例如,若是检测的浏览器支持boxshadow这个CSS3属性,Modernizr就会在标签上添加boxshadow类,不然,就会添加no-boxshadow类。下图显示的是在chrome 23.0.1271.64版本上的HTML5和CSS3新特性支持状况。异步
而后,你只须要在你的CSS样式表中定义相应的样式信息便可,你能够像下面这样定义:
1 |
.boxshadow #MyContainer { |
2 |
border : none ; |
3 |
-webkit-box-shadow: #666 1px 1px 1px ; |
4 |
-moz-box-shadow: #666 1px 1px 1px ; |
5 |
} |
6 |
.no-boxshadow #MyContainer { |
7 |
border : 2px solid black ; |
8 |
} |
因为浏览器会忽略不支持的CSS3特性,若是当前的浏览器版本不支持boxshadow属性,它会忽略掉boxshadow类,转而引用no-boxshadow类中定义的样式,省去了你在js程序中检测浏览器名称的麻烦逻辑。
固然,当你的应用场景须要你在程序中判断是否支持某种新特性而给出不一样的处理逻辑时,你也能够利用Modernizr很容易地进行判断,此时,你须要用到Modernizr建立的一个命名为”Modernizr”的全局对象,其内容是为每个检测完的特性给出的布尔值结果所组成的列表,若是浏览器支持boxShadow属性,那么Modernizr.boxShadow的值就是true,不然为false,因此引入库文件后,你也可使用此种方法来检测浏览器对该特性的支持状况。这个js对象针对某些功能还包含了更为详细的信息,如”Modernizr.video.h264”会告诉你浏览器是否支持这个特殊的编解码器,”Modernizr.inputtypes.search”会告诉你当前浏览器是否支持新的search input类型。
此外,若是Modernizr中并不包含你须要检测的特性,你能够调用Modernizr封装的addTest函数来测试,针对不一样的HTML5和CSS3特性,咱们能够在github(因为某种缘由,Modernizr被封,该项目现托管在github上)上找到不少已经写好的addTest函数。咱们仍是一块儿来看一个简单的例子,若是你想测试浏览器是否支持getusermedia这个API(WebRTC新技术中的API),你能够编写下面这样的addTest函数来测试:
1 |
Modernizr.addTest( 'getusermedia' , !!Modernizr.prefixed( 'getUserMedia' , navigator)); |
相信简单的介绍以后,你已经初步体会到了Modernizr能为开发带来的便利之处了。了解了Modernizr的功能和如何使用Modernizr后,看看它的源码熟悉它的实现原理一样能学习到很多新知识。Bella在这方面虽然是菜鸟一个,可是仍是跟你们分享一点看源码的心得。
前面bella提到过Modernizr这个全局对象,具体它在Modernizr里是怎样建立的呢?咱们来看下面源码:
1 |
window.Modernizr = ( function ( window, document, undefined) { |
2 |
var ...; |
3 |
Modernizr = {}; |
4 |
... |
5 |
return Modernizr; |
6 |
})( this , this .document); |
这部分代码用异步函数产生了一个命名空间(虽然js中并无真正意义上的命名空间),函数返回了一个Modernizr对象,而这个对象被分配到了window.Mordernizr下,这样,其余的js程序就能够直接使用window.Modernizr或Modernizr对象。函数被调用时传入的参数this指的是函数执行的上下文环境,也即window这个全局对象。
Modernizr是如何测试对CSS3新特性的支持程度的呢?原来Modernizr会先建立一个DOM对象,而后利用这个对象下的style属性来测试是否支持各CSS3新特性。代码以下:
1 |
var mod = 'modernizr' , |
2 |
modElem = document.createElement(mod), |
3 |
mStyle = modElem.style; |
对浏览器而言,不管它是否可以识别咱们新建立的html标签,咱们均可以给它设定样式,因此咱们能够给这里新建立的标签设置样式。假设咱们想测试浏览器是否支持CSS中用hsla来定义颜色,咱们能够先写一个应用了hsla属性的样式放到标签下,而后检查样式的值是否含有hsla的字符串,若是浏览器不支持,就不会有hsla字符串(由于将应用了hsla属性的样式放到modernizr标签下的动做根本就不会生效)。咱们能够编写以下代码:
1 |
tests[ 'hsla' ] = function () { |
2 |
setCss(‘background-color:hsla(120,40%,100%,.5)’); |
3 |
return contains(mStyle.backgroundColor, 'rgba' ) || |
4 |
contains(mStyle.backgroundColor, 'hsla' ); |
5 |
}; |
这里因为有些浏览器会将hsla的表示法转成rgba,因此同时检查是否有rgba这个字符串。
而对于带有供应商前缀的CSS属性,咱们还需给出不一样的处理。回到boxShadow属性上,Modernizr会去测试上面建立的mStyle变量下是否有boxShadow、WebkitBoxShadow、MozBoxShadow、OBoxShadow、msBoxShadow或KhtmlBoxShadow属性,若是有则表示浏览器支持该属性。这里主要用到了两个Modernizr封装的函数,一个是testProp(),一个是testAllProps()。Modernizr.testProp(str)会返回一个给定的样式属性是否能被识别,而Modernizr.testAllProps(str)会返回一个给定的样式属性,或者是任意带有供应商前缀的样式属性是否能被识别。
有关更多的源码知识,等bella之后有更深刻的研究后再跟你们介绍吧。bella相信若是你熟悉了Modernizr的原理和使用方法,它必定可以帮助你提升开发效率。
最后,bella简单总结了一些可供你们学习Modernizr的资料:
1. Modernizr官网: http://modernizr.com/docs/ 你能够在上面学习到Modernizr知识,源码和下载Modernizr。
2. Modernizr Test Suite网址:http://modernizr.github.com/Modernizr/test/index.html 你能够在上面查询到各浏览器对HTML5和CSS3特性支持状况,查询方法:
点击该页面下方的Show the Ref Tests from Caniuse and Modernizr,而后任意单击一个测试的HTML5或CSS3特性的Table连接,便可看到各浏览器支持状况。
3. shim/polyfill脚本的相关信息: https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-Browser-Polyfills
4. 各类检测HTML5和CSS3新特性的addTest函数下载地址:
https://github.com/Modernizr/Modernizr/tree/master/feature-detects