摘要:關於各類瀏覽器模式,網上已經有許多文檔和資料了,可是不多有可以徹底將幾個概念闡述清楚的。大部分的資料稍顯過期,有些內容可能已經再也不適用了。本文中筆者將盡量將幾個概念闡述清楚,並去掉一些過期的內容,僅保留必要的乾貨。 javascript
想必你必定知道瀏覽器有個標準(Standards)模式和一個怪異(Quirks)模式,或許你還據說過有個「準標準(Almost Standards)」模式。而當你打開Internet Explorer的時候,又看到了什麼瀏覽器模式、文檔模式,還有什麼兼容性視圖等等... css
這些都是什麼?啥是瀏覽器模式,啥是文檔模式?標準模式和準標準的模式有什麼區別?IE9兼容性視圖和真正的IE9有什麼區別?什麼狀況下會觸發這些模式,又該怎樣才能檢測到瀏覽器當前處於哪一種模式中呢?本文將詳細爲你解答這些疑問。 html
三種模式 html5
首先咱們要知道,爲何會有這麼多模式。其實這是個歷史遺留問題,在瀏覽器大戰時期,網景瀏覽器(Netscape Navigator)和微軟的IE瀏覽器(Microsoft Internet Explorer)對網頁分別有不一樣的實現方式,那個時候的網頁要針對這兩種瀏覽器分別開發不一樣的版本。而到了W3C制定標準以後,這些瀏覽器就不能繼續使用這種頁面了,於是會致使大部分現有站點都不能使用。基於這個緣由,瀏覽器才引入兩種模式來處理一些遺留的站點。 java
如今的瀏覽器排版引擎支持三種模式:怪異(Quirks)模式、準標準(Almost Standards)和標準(Standards)模式。在怪異模式中,排版引擎會模擬 網景4和Windows中的IE5的行爲;在徹底標準的模式中,會盡可能執行HTML和CSS規範所指定的行爲;而在準標準模式中,則只包含不多的一部分怪異模式中的行爲。 web
那麼所謂標準模式,就必定都「標準」嗎?答案固然是否認的,由於各個瀏覽器廠商實現標準的階段不一樣,因此各個瀏覽器的「標準模式」之間也會有很大的不一樣。 瀏覽器
Firefox、Safari、Chrome、Opera (自 7.5 之後)、 IE8 和 IE9 都有一個準標準模式。那麼既然標準模式都不那麼標準,準標準的模式確定就更不標準了。最初的準標準模式只會影響表格中的圖像,然後來各個瀏覽器又或多或少地進行了修改。那麼什麼狀況下會觸發準標準模式呢?是的,正如你所想到的,某些DOCTYPE會觸發準標準模式,例如:服務器
"-//W3C//DTD XHTML 1.0 Transitional//EN""-//W3C//DTD XHTML 1.0 Frameset//EN""-//W3C//DTD HTML 4.01 Transitional//EN""-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd"
一個完整的 DOCTYPE 例子以下: app
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
若是在Firefox中插入這種DOCTYPE,並在頁面中插入一個空的span標籤,那麼在Firebug中查看元素的佈局就會發現不一樣: less
準標準模式中元素的line-height被忽略了,元素既沒有寬度也沒有高度:
標準模式中元素仍然保留了line-height,擁有18px的高度:
在Firefox瀏覽器中,使用鼠標右鍵->查看頁面信息 能夠看到當前瀏覽器運行在何種模式(只能看到「混雜模式」和「標準規範模式」兩種表示):
有位大神Henri Sivonen曾寫過一篇文章叫作Activating Browser Modes with Doctype,裏面包含了一個完整的表格,展現了各類DOCTYPE設置將會使瀏覽器以何種方式渲染。這裏還有一篇秦歌的譯文《用doctype激活瀏覽器模式》。
鑑於目前一些最新版本的瀏覽器已經放棄了準標準模式,因此關於準標準模式的細節這裏就再也不贅述了,感興趣的同窗能夠詳細閱讀如下資料:
那麼,既然這麼多的DOCTYPE都會觸發非標準的模式,那麼如何才能觸發標準模式呢?對了!要使用HTML5 DOCTYPE,即:
<!DOCTYPE html>
注意:若是文檔中沒有包含DOCTYPE或者包含了一個沒法識別的DOCTYPE,則瀏覽器就會進入怪異模式。
下面簡單說一下怪異模式。怪異模式有許多「怪異」的行爲,主要是爲了兼容那些遺留的古老頁面而保留的模式。不一樣瀏覽器的怪異模式也不盡相同,它們都有本身的實現方式。怪異模式與標準模式的差別主要體如今 盒模型(box model)、表格單元格高度的處理等。例如IE的怪異模式中,元素的width包含了padding和border,而標準模式中padding和 border 並不屬於寬度的一部分。
若想詳細瞭解瀏覽器在怪異模式下的行爲,能夠參看下面兩篇文章。不過不建議在這上面花太多的精力,這是個歷史遺留問題,並且咱們也儘可能保證新開發的頁面不要進入到怪異模式:
小結:至此咱們須要瞭解,瀏覽器有三種運行模式,即標準模式、準標準模式和怪異模式,要使用 <!DOCTYPE html> 來正確地觸發標準模式。千萬不要丟掉DOCTYPE聲明,由於這會致使瀏覽器進入怪異模式。
IE的瀏覽器模式
IE8有4種模式:IE5.5怪異模式、IE7標準模式、IE8準標準模式和IE8標準模式,而IE9有7種模式: IE5.5怪異模式、IE7標準模式、IE8準標準模式、IE8標準模式、IE9準標準模式、IE9標準模式、XML模式。
其中XML模式是針對XML文檔的,這裏不打算闡述,細節能夠看這篇文章[Defining Document Compatibility](http://msdn.microsoft.com/en-us/library/cc288325(v=vs.85).aspx) 中有詳細闡述。
在IE8及之後的的IE瀏覽器中,支持X-UA-Compatible頭,能夠經過在服務器端設置HTTP頭,或者在頁面中插入<meta>標籤來實現:
- HTTP:
- Header set X-UA-Compatible "IE=8"
- Meta:
- <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
這種方法主要是防止老的頁面在較新的瀏覽器中顯示不正常的狀況的, 好比上面的代碼能夠強制IE8以上版本的瀏覽器以IE7的模式進行渲染。
注意,不要在新開發的網頁中使用這種技術,這種技術只應該做爲新老網頁更替過程當中的過渡方案。因爲目前新開發的網頁都是儘可能支持最新版本的瀏覽器的,因此這種技術也會慢慢被淘汰,感興趣的同窗能夠詳細閱讀 微軟的這篇文檔。
小結:這裏咱們須要知道有這種方式能夠強制瀏覽器以某種模式運行,但只應做爲過渡方案,不該在新開發的網頁中使用。
IE9兼容性視圖與IE9標準視圖
若是你使用的是IE9,那麼按下F12鍵就會出現開發者工具,上面有兩個下拉菜單:瀏覽器模式和文檔模式。那麼什麼是瀏覽器模式?什麼又是文檔模式?兩者有何區別?
瀏覽器模式用於切換IE針對該網頁的默認文檔模式、對不一樣版本瀏覽器的條件註釋解析、以及發送給網站服務器的用戶代理(User-Agent)字符串的值。網站能夠根據瀏覽器返回的不一樣用戶代理字符串判斷瀏覽器的版本和及安裝的功能,這樣就能夠根據不一樣的瀏覽器返回不一樣的頁面內容了。
文檔模式用於指定IE的頁面排版引擎(Trident)以哪一個版本的方式來解析並渲染網頁代碼。切換文檔模式會致使網頁被刷新,但不會更改用戶代理字符串中的版本號,也不會從服務器從新下載網頁。切換瀏覽器模式的同時,瀏覽器也會自動切換到相應的文檔模式。
一言以蔽之,瀏覽器模式會影響服務器端對客戶端瀏覽器版本的判斷,對條件註釋也有影響;而文檔模式會影響IE的排版引擎,對網頁渲染會有影響,對CSS hack也會產生影響。所以,經過條件註釋能夠判斷瀏覽器模式,而使用CSS hack能夠判斷文檔模式。
若是咱們使用一句簡單的JavaScript語句來查看用戶代理(User-Agent)字符串的值,則能夠看到IE9兼容性視圖與IE9的區別:
<script type="text/javascript">alert('UA:'+navigator.userAgent);</script>
輸出結果以下所示,注意其中的MSIE版本號已經不一樣。判斷瀏覽器模式就是判斷User-Agent中的版本號,即MSIE後面的數值:
- // IE9
- UA:Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; Tablet PC 2.0)
- // IE9 兼容性視圖
- UA:Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; Tablet PC 2.0)
話說IE9兼容性視圖是模擬IE7的行爲,那麼IE9兼容性視圖與IE7有沒有區別呢?確定是有區別的,即便是IE9中的IE7標準模式,與原生的IE7在渲染上也是有區別的,具體咱們暫不去深究。
那麼既然IE9兼容性視圖的版本號跟IE7相同,如何才能判斷當前是IE9兼容性視圖,仍是純正的IE7呢?其實很簡單,只須要判斷瀏覽器的用戶代理(User-Agent)字符串中是否包含Trident便可。首先檢測MSIE的版本號是否爲7.0,而後再判斷是否含有Trident字串,若包含則爲IE9兼容性視圖,不然則爲純正的IE7。
小結:至此,你應該瞭解了什麼是瀏覽器模式、什麼是文檔模式以及它們之間的區別了,另外還了解了IE9兼容性視圖與IE9以及IE7的區別。
控制默認的渲染方式
當Internet Explorer 9遇到未包含X-UA-Compatible標頭的網頁時,它將使用<!DOCTYPE>指令來肯定如何顯示該網頁。 若是該指令丟失或未指定基於標準的文檔類型,則Internet Explorer 9將以IE5模式(怪異模式)來顯示該網頁。
若是<!DOCTYPE>指令指定了基於標準的文檔類型,則Internet Explorer 9將以IE9模式顯示該網頁,但出現如下狀況時除外:
此外,可使用下面的註冊表項來控制Internet Explorer對未包含X-UA-Compatible標頭的頁面的處理方式。
HKEY_LOCAL_MACHINE (or HKEY_CURRENT_USER) SOFTWARE Microsoft Internet Explorer Main FeatureControl FEATURE_BROWSER_EMULATION iexplore.exe = (DWORD)
其中DWORD值必須等於下列值之一:
值 說明
7000 包含基於標準的 <!DOCTYPE> 指令的頁面將以 IE7 模式顯示。
8000 包含基於標準的 <!DOCTYPE> 指令的頁面以 IE8 模式顯示。
8888 頁面始終以 IE8 模式顯示,而不考慮 <!DOCTYPE> 指令。 (這可繞過前面列出的例外狀況。)
關於IE瀏覽器肯定文檔模式的整個流程,能夠參看這篇文章How IE8 Determines Document Mode,文中詳細闡述了整個流程與內部機制。
小結:仍然堅持使用<!DOCTYPE html>,可最大程度減少發生錯誤的概率。
文檔模式的檢測
在JavaScript中能夠經過documentMode來檢測文檔模式,在IE6和IE7中是使用compatMode來肯定文檔模式的,這個屬性自IE8開始已經被documentMode所替代。
那麼,若是須要兼容IE6和IE7的話(必須的 ...),則相應的檢測代碼大體以下:
- engine = null;
- if (window.navigator.appName == "Microsoft Internet Explorer")
- {
- // This is an IE browser. What mode is the engine in?
- if (document.documentMode) // IE8 or later
- engine = document.documentMode;
- else // IE 5-7
- {
- engine = 5; // Assume quirks mode unless proven otherwise
- if (document.compatMode)
- {
- if (document.compatMode == "CSS1Compat")
- engine = 7; // standards mode
- }
- // There is no test for IE6 standards mode because that mode
- // was replaced by IE7 standards mode; there is no emulation.
- }
- // the engine variable now contains the document compatibility mode.
- }
IE6和IE7中的compatMode有兩個可能的值「CSS1Compat」和「BackCompat 」,分別對應了IE6和IE7中的標準模式和怪異模式。上面的代碼首先假定是怪異模式,而後再試圖推翻假設。這裏沒有包含「IE6 標準模式」,由於它已經被IE7標準模式所替代,沒有模擬的狀況。
這裏要注意,不一樣的文檔模式對JavaScript也有一些影響,咱們沒必要去深究不一樣文檔模式對JavaScript有何種不一樣影響,只須要在編碼時進行特定的特性檢測便可。
小結:通常狀況下是不必進行文檔模式檢測的,對於樣式兼容咱們能夠寫CSS hack,而對於JavaScript來講,則更加推薦特性檢測,而不是檢測瀏覽器自己。
瀏覽器模式與文檔模式之間的關係
瀏覽器模式能夠決定頁面默認的文檔模式,但文檔模式可能會受其餘因素影響而改變,如上文所述。若是瀏覽器模式與文檔模式設置不一樣的話,會不會有什麼影響呢?
咱們已經知道瀏覽器模式主要用於標識瀏覽器自己,原則上不會對頁面渲染產生影響。可是咱們又知道,瀏覽器模式能夠影響條件註釋,因此若是你的頁面中有條件註釋的話,那麼瀏覽器模式的變化就會影響到頁面渲染。
服務器端只能經過瀏覽器模式所標識的版原本肯定客戶端瀏覽器的版本,若是你將瀏覽器模式標識爲IE9,但文檔模式選擇爲IE7標準的話,就可能會有問題。不過這還要看服務器端是否有針對不一樣瀏覽器的處理策略,若是服務器端並未對不一樣瀏覽器的輸出作差別化處理的話,那麼這兩個模式選項不一樣就不會有問題。
小結:若是服務器端對不一樣瀏覽器的輸出作了差別化處理,那麼瀏覽器模式和文檔模式不一致就可能產生問題。
結語
本文參考了大量現有文獻,詳細闡述了各類模式的區別以及它們之間的關係。相信經過上面的敘述,你已經可以區分這些瀏覽器模式或者文檔模式以及它們之間的關係了,每節的結論在小結中已有闡述,但願可以對你有所幫助。
來自:圖靈社區