隨着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