隨著HTML5和CSS3的飛速發展,越來越多語義化的標籤和炫酷的特性被應用到web應用開發中來,各大瀏覽器廠商紛紛開始支持這些新特性,web開發人員也都興趣十足地試用這些新特性開發出更絢麗有趣的應用,但是各大瀏覽器對這些新特性參差不齊地支持(尤其是令人頭疼的IE)所帶來的版本兼容性問題始終都是縈繞在開發人員心頭的噩夢。傳統的使用習慣使得我們很難摒棄老版本瀏覽器,開發人員只能選擇令人厭煩的手工測試,測試,再測試。
為了解決這一難題,Modernizr應運而生了。它的名字聽起來有點像Modernize, 確實,該名字起源於使得開發體驗能夠更現代化的目的,但它並非試圖使舊的瀏覽器現代化,也就是使它支持這些新特性(儘管你確實可以通過添加shim/polyfill腳本來讓瀏覽器支持某些不支持的新特性,後面會介紹)。
Modernizr是一個檢測瀏覽器對HTML5和CSS3特性支持的開源的js庫,著名的HTML5/CSS3瀏覽器兼容性網站FindmeByIP就是基於該框架實現的。我們能夠利用它來檢測瀏覽器是否支持某種新特性,甚至可以額外加載script腳本,滿足你根據不同的情況動態加載不同的js文件來減少下載量提高性能的需求。
Modernizr提供development和production兩個版本,development版本包含了對所有HTML5和CSS3新特性的檢測,適用於學習和測試,對於剛開始使用Modernizr的新手來說,bella建議你使用這個版本。當你熟悉了Modernizr的工作原理後,你就可以使用production這個自定義版本,你可以只下載任意數量的你需要檢測的特性從而大大減小下載量,這在某種程度上是能小幅提高你程序的性能的。你可以在http://modernizr.com/download/上下載這兩個版本,點擊該頁面上的development version鏈接,就可以下載development版,或者,你已經看到瞭如下的特性顯示頁面
你可以勾選任意你想要測試的HTML5或CSS3特性,但是默認情形下,Extra分類將會選中如下三項:
a) HTML5 Shiv v3.6:它添加了一個腳本— HTML5 shim 它會迫使迫使IE6-8 正確地設計並打印HTML5 元素。如果你打算使用新的HTML5 語義標籤,例如<header>、<footer>、 <nav>、<section>、<article>等等,那麼你需要選這個選項。
b) Modernizr.load(yepnope.js):它添加了一個不包含在development 版本中的可選擇的腳本加載器。它增加了3KB 的下載量,所以如果你不需要它,你可以放棄選擇它。
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
本文出自Tencent Wuhan Blog,轉載時請註明出處