怪異模式(Quirks Mode)對 HTML 頁面的影響
轉載自:http://www.ibm.com/developerworks/cn/web/1310_shatao_quirks/#ibm-pcon
本文主要描述 Quirks Mode 和 Standards Mode
這兩種文件模式渲染頁面時的差異由來,並且給出一些詳細的例子說明差異所在。通過閱讀本文,Web 開發工程師可以對瀏覽器工作原理有更為深刻的理解,避免自己所開發的 Web 應用在不同的瀏覽器上產生不同的效果。
Quirks Mode 概述
定義
什麼是 Quirks Mode? 簡單來說,Quirks Mode 就是瀏覽器為了相容很早之前針對舊版本瀏覽器設計、並未嚴格遵循 W3C 標準的網頁而產生的一種頁面渲染模式。
歷史
由渲染引擎產生的兩種文件模式
談到 Quirks modes 首先就要從瀏覽器渲染引擎說起。我們知道所有的瀏覽器都有自己的頁面渲染引擎,渲染引擎主要包含兩部分,一部分負責 HTML、CSS 程式碼的解析,另一部分負責指令碼程式碼解析,這兩部分合起來就可以繪製出完整的頁面。
表 1 各瀏覽器渲染引擎構成
IE | Trident | -- | Chakra |
---|---|---|---|
Firefox | Gecko | -- | SpiderMonkey |
Chrome | Webkit | Webcore | V8 |
Safari | Webkit | Webcore | Javascriptcore |
Opera | Presto | -- | Carakan |
從表 1 可以看出,現在市面上的主流瀏覽器中除了 Chrome 和 Safari 都採用了 Webkit 渲染引擎,其餘三種瀏覽器採用了各自不同的渲染方式(不同的 HTML 解析,不同的 JS 解析)。我們這裡暫且先不討論不同的渲染引擎繪製頁面時的差異,單以每一種渲染引擎而言,隨著版本的發展其渲染頁面的方式也有很大的不同。
IE 是最早提出 Quirks Mode 與 Standards Mode(與 Quirks 相對應的一種模式)的,後來 Firefox、Chrome、Safari、Opera 等瀏覽器也都支援了這兩種渲染方式。但是隻有在 IE 中使用者才可以自由地在兩種方式之間切換,其他瀏覽器都是自動匹配其中一種。下文將主要以 IE 為例來說明 Quirks Mode 對頁面繪製的影響,表 2 展示了 IE 隨著其渲染引擎的發展,它對 HTML 頁面的渲染改變如下。
表 2 IE 渲染引擎發展歷史
Trident 版本 | MSHTML.dll 版本 | IE 版本 | 更新 |
---|---|---|---|
unversioned | 4.0.x | 4 | 首發 |
unversioned | 5.0.x | 5 | 增加對 CSS1 的支援及改變對 CSS 的渲染 |
unversioned | 5.5.x | 5.5 | 修正部分 CSS 的排版控制 |
unversioned | 6.0.x | 6 | 修正 box model 的錯誤及新增 quirks Mode 的切換功能 |
unversioned | 7.0.x | 7 | 修正部分 CSS 排版錯誤以及增加對 PNGalpha 通道(半透明) |
4.0 | 8.0.x | 8 | 第一個通過 Acid2 測試的版本 |
5.0 | 9.0.x | 9 | 首次支援 HTML5、SVG、CSS3 及採用新的 JavaScript 引擎 |
6.0 | 10.0.x | 10 | 支援 CSS3 多欄式排版、格子對齊、浮動式區塊排版、漸變 |
從表 2 可以清晰的看出,隨著 IE 的發展,其渲染引擎(早期為 MSHTML.dll,後來命名為 Trident)也在不斷加入新的特性以及修正一些早先版本的錯誤。在 2001 年 IE6 正式釋出之前,當時的市面主要就是 IE 和 Netscape 的 Navigator 兩款瀏覽器,而 IE 擁有很大的使用者群,所以大多數的頁面都是針對 IE 而設計的,但是 IE 的渲染引擎卻沒有遵循 W3C 的規範,當時微軟已經認識到 W3C 規範的重要性,所以當 IE 發展到 IE6 的時候,渲染引擎(MSHTML.dll)做出了一個重要的改變,將自己原先不符合 W3C 規範中的盒模型 box mode 繪製方式改為與 W3C 標準一致(後面會詳細討論),由於這個重大的改動,原先針對 IE 舊版本所設計的 HTML 頁面都不能正確顯示了,所以在 IE6 釋出的時候附帶了一個切換回 IE5 頁面渲染方式的功能,這個功能中就首次提出了 Quirks Mode。
當用戶需要顯示舊版本的頁面時切換到 Quirks Mode,這時瀏覽器的渲染引擎就切換到 IE5.5 所對應的版本(MSHTML.dll 5.5.x),box mode 還是按照之前的方式繪製,這樣頁面就可以正確顯示。當用戶需要顯示一些新的、滿足 W3C 規範的頁面時,渲染引擎切換到一個與 Quirks Mode 對應的 Standards Mode(標準模式),在此模式下渲染引擎就是當前的最新版本,這樣也就滿足了更多的 W3C 規範。這兩種 Mode 之間的差別就是因為工作在不同版本的渲染引擎環境下。
最後,Quirks Mode 和 Standards Mode 合起來就稱為瀏覽器的文件模式 Document Mode。
Quirks 和 Standards 之外的第三種模式
實際上,在上文提到的具有 Quirks 和 Standards 兩種文件模式的瀏覽器中還存在第三種模式—Almost Standards Mode。這種模式和 Standards Mode 幾乎一致,唯一的區別就在於某些情況下 Almost Standards Mode 會採用與 Quirks 相同的方式來繪製頁面。比如當我們需要把圖片分割後顯示在一個表格單元中時,Almost Standards Mode 與 Quirks Mode 採用同樣的繪製方式從而讓圖片顯示不像在 Standards Mode 中那麼的四分五裂。
但是這只是極少數的情況,在大部分情況下 Almost Standards 和 Standards 兩種模式是一致的,所以我們一般不專門區分二者,後面我們會提到如何檢視瀏覽器渲染引擎資訊,在這個資訊中同樣對 Almost Standards Mode 和 Standards Mode 是不做區分的。
Quirks Mode 有兩種
如果我們將 IE 升級到最新的 IE10 就會發現 IE10 除了擁有 IE7/8/9/10 Standards Mode 四種 Standards Mode,同樣還有擁有了兩種 Quirks Mode:IE5 Quirks 和 IE10 Quirks。隨著 IE10 釋出而產生的這個新的怪異模式 IE10 Quirks 被認為是一種更好的支援了 HTML5 規範的 Quirks Mode。我們可以發現針對 HTML5 規範而設計的頁面(如含有<audio>、<video>、<canvas>等標籤)在 IE5Quirks 下是不能正確顯示的,但是在 IE10 Quirks 下完全可以正確顯示。也就是說,IE10 Quirks 是為了在那些針對 HTML5 設計,但是又沒有新增 doctype(可以決定瀏覽器工作在哪種模式下,後面會詳細討論)的頁面而存在的。
如何檢視 Document Mode
IE 中,使用者可以在 developer tools 中切換模式,如圖 1 所示,IE10 的六種文件模式都被顯示在 Document Mode 選單下,使用者可以直接選擇,下一章的 Demo 我們都採用 IE10(version: 10.0.9200.16576)作為測試瀏覽器。
圖 1 IE Document Mode
除了從 developer tools 中檢視,還有可以從 document 物件的屬性 compatMode 中獲知文件模式,這個屬性只有兩個值 BackCompat 和 CSS1Compat,前者對應的是 Quirks Mode 後者對應 Standards Mode。在 developer tools 中切換文件模式時,頁面會自動重新整理,compatMode 的值也會隨之改變。
瀏覽器如何判斷文件型別?
上一節中我們知道 IE 使用者可以在 developer tools 中改變文件模式。那麼,如果使用者沒有自己選擇,瀏覽器在準備解析、繪製一個頁面的時候,它是如何決定文件模式的呢?實際上瀏覽器在渲染頁面之前會檢查兩個內容,一個是頁面是否有 doctype 資訊,另外一個是頁面是否有 x-ua-compatible 資訊。
Doctype 檢測
對於一個 HTML 頁面,<!DOCTYP >宣告位於其中最前面的位置,處於<html>標籤之前,這個<!DOCTYP >可以告知瀏覽器使用哪種 HTML 規範,針對每種規範瀏覽器同樣也會選擇對應的文件模式。平時最常見的三種 doctype 資訊對應的文件模式如下。
- 當 doctype 資訊如下時,表明該頁面是遵守了 HTML5 規範的,瀏覽器會選擇 Standards Mode,這種 doctype 是最推薦的一種,我們平時設計頁面都應該加上這一個 doctype。
<!DOCTYPE html>
- 當 doctype 如下時,瀏覽器同樣會選擇 Standards Mode,雖然和第一種 doctype 有一些區別,但是幾乎可以認為是一樣的。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
- 當 doctype 如下時,瀏覽器會選擇 Almost Standards Mode,需要注意的是如果今後需要把這個頁面改為 HTML5 規範,那麼上文討論的<table>中的分割圖片問題可能會錯亂。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
- 當 doctype 缺失的時候,瀏覽器會選擇 Quirks Mode,這是非常不推薦的方式,我們應該儘量避免 Quirks Mode,這對一個 web 應用是非常不利的地方。
x-ua-compatible 資訊
除了上一節提到的 doctype 檢測,HTML 頁面的開發者可以在頁面的<head>標籤中加入 x-ua-compatible 資訊來影響文件型別的判定,具體如下表所示。
表 3 x-ua-compatible 影響文件型別
x-ua-compatible | doctype | Document Mode |
---|---|---|
<meta http-equiv="X-UA-Compatible" content="IE=5" > | 無影響 | IE5 quirks |
<meta http-equiv="X-UA-Compatible" content="IE=7/8/9/10" > | 無影響 | IE7/8/9/10 Standards |
<meta http-equiv="X-UA-Compatible" content="IE=Edge" > | 無影響 | IE 最新版本的 Standards |
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7/8/9" > | <!DOCTYPE html> | IE7/8/9 Standards |
不存在 | IE5 quirks | |
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE10" > | <!DOCTYPE html> | IE10 Standards |
不存在 | IE10 quirks |
從表 3 可以看出,一般情況下 x-ua-compatible 是優先於 doctype 的設定的,但是當 x-ua-compatible 設定了如“EmulateIExx”的情況時,就會同樣考慮到 doctype 的影響。
另外,在<head>中加入 x-ua-compatible 資訊與在請求訊息的 header 中加入是等同的,如下程式碼效果是等同的。
response.setHeader("X-UA-Compatible","IE=Edge"); <meta http-equiv="X-UA-Compatible" content="IE=Edge" >
到現在為止我們分析了 Quirks Mode 產生的歷史、對瀏覽器的影響以及瀏覽器如何選擇文件模式。下一章我們主要討論兩種不同的文件模式下渲染頁面的差別。
標準模式下的頁面與怪異模式下的頁面區別
這一章我們主要選擇一些典型的例子來說明 Quirks Mode 和 Standards Mode 對頁面渲染的影響。
盒模型
前面提到,盒模型(box mode)是瀏覽器 Quirks Mode 和 Standards Mode 的主要區別。
描述
對於“盒模型”一詞並沒有明確的文件定義,它是開發人員描述 CSS 中塊級元素的一種約定俗稱。
具體而言,針對一個塊級元素,如<p>、<div>、<span>等,CSS 的規範定義了一個寬度和高度,以及 3 個級別的環繞它的框 padding、border 和 margin 。這些屬性我們可以把它轉移到我們日常生活中的盒子上來理解,所以將這種模型稱為盒模式。對於盒模型,針對高度和寬度的定義,不同瀏覽器的解釋不同。
出於歷史原因,早期的 IE 瀏覽器(IE 6 以前)將盒子的 padding 和 border 算到了盒子的尺寸中,這一模型被稱為 IE 盒模型。該模型如圖 2.1 所示,
圖 2 IE 盒模型
在 IE 盒模型中,
box width = content width + padding left + padding right + border left + border right,
box height = content height + padding top + padding bottom + border top + border bottom,
而在 W3C 標準的盒模型中,box 的大小就是 content 的大小,如圖 3 所示,
圖 3 W3C 標準盒模型
box width = content width,
box height = content height,
這一區別將導致頁面繪製時所有的塊級元素都出現很大的差別,所以兩種不同的文件模式下的頁面也區別很大。
示例展示
如下程式碼段所示,我們定義一個簡單的 DIV 元素,設定其寬度和高度分別為 500px,定義 border 為 50px,紅色。
清單 1
div.a{ width:500px; height:500px; border:50px; border-style:solid; border-color:red; }
分別在 IE 5 Quirks Mode 和 IE 8 Standards Mode 下執行,結果如圖 4 和 5 所示。明顯可以看到,在 Standards Mode 下的 DIV 要大於 Quirks Mode,其實際渲染大小為 600px*600px。
圖 4 IE 5 Quirks Mode
圖 5 IE 8 Standards Mode
圖片元素的垂直對齊方式
CSS 中 vertical-align 屬性用於設定或檢索物件內容垂直對齊方式,該屬性定義行內元素的 base line 相對於該元素所在行的 base line 的垂直對齊。在表單元格中,這個屬性會設定單元格框中的單元格內容的對齊方式。其取值可以為 baseline,sub,supper,top,text-top,bottom,text-bottom,middle 等。什麼是 baseline 和 bottom,它們有何區別?下面我們通過一副圖來進行解釋。
描述
CSS 為了確定文字行的位置,定義如下概念描述,base line,bottom line,top line, middle line。其中,base line 指的是一行字橫排時下沿的基礎線,baseline 並不是漢字的下端沿,而是英文字母 e 的下端沿,bottom line,指的是漢字,或者英文字母 p,g 的下端沿。如下圖 6 所示。
圖 6 base line 概念
對於 inline 元素和 table-cell 元素,在 IE Standards Mode 下 vertical-align 屬性預設取值為 baseline。而當 inline 元素的內容只有圖片時,如 table 的單元格 table-cell。在 IE Quirks Mode 下,table 單元格中的圖片的 vertical align 屬性預設為 bottom,因此,在圖片底部會有幾畫素的空間。
示例展示
如下程式碼段所示,我們定義一行兩列的 table,table 單元格設定為寬度和高度均為 200px 的 img 圖片,為了突出顯示區別,分別定義單元格與圖片的邊框顏色為藍色和橘色。
清單 2
td.a { border-style:solid; border-color:blue; } img.c { width:200px; height:200px; border-style:solid; border-color:orange; }
分別在 IE 10 Quirks Mode 和 IE 8 Standards Mode 下執行,結果如圖 7 和 8 所示。在 Quirks Mode 下,table 單元格中的圖片與單元格底部對齊,而在 Standards Mode 下,圖片與單元格之間多了 3 個畫素的空間。
圖 7 IE 10 Quirks Mode
圖 8 IE 8 Standards Mode
<table>元素中的字型
CSS 中,描述 font 的屬性有 font-family,font-size,font-style,font-weight,分別表示了 font 的族系、大小、風格以及粗細。
描述
在 CSS 標準中,上述屬性都是可以繼承的。而在 IE Quirks Mode 下,對於 table 元素,字型的某些屬性將不會從 body 或其他封閉元素繼承到 table 中,特別是 font-size 屬性。
示例展示
如下程式碼段所示,我們定義 body 的 font 屬性為斜體、紅色、加粗、fantasy 字型,對於 table 元素,未定義其 font 屬性。
清單 3
body { font-style:italic; color:red; font-size:200%; font-weight:bold; font-family: fantasy; }
分別 IE 5 Quirks Mode 和 IE 8 Standards Mode 下執行,結果如圖 9 和 10 所示。在 Quirks Mode 下,table 單元格中字型的 font-size,font-style,font-weight 屬性不會繼承 body,只有 family 屬性會被繼承。而在 Standards Mode 下,所有屬性都被繼承。
圖 9 IE 5 Quirks Mode
圖 10 IE 8 Standards Mode
內聯元素的尺寸
CSS 中常見的元素有兩類,分別是 block(塊級)元素及 inline(內聯)元素。這兩類元素的主要區別在於 block 元素通常作為獨立的一塊繼續顯示,前後都有換行,而 inline 元素則不會產生換行。根據 CSS 標準,對於 inline 元素,又可以分為 replaced 和 non-replaced 兩類。
描述
什麼是 non-replaced inline 元素?首先,我們解釋下 non-replaced 元素,對於 HTML 中定義的元素,預設具有 CSS 格式化外表範圍的元素,比如 img 元素,有自己的寬和高,我們稱其為 replaced 元素,其他例 input,textarea,select,object,等都是 replaced 元素。除了這些元素之外的元素就是 non-replaced 元素。因此,具有 non-replaced 屬性的 inline 元素即為 non-replaced inline 元素,如 span 元素。
在 IE Standards Mode 下,non-replaced inline 元素無法自定義大小,而在 IE Quirks Mode 下,定義這些元素的 width 和 height 屬性,能夠影響該元素顯示的大小尺寸。
示例展示
如下程式碼段所示,為了突出顯示,我們定義一個背景色為橘色的 div 中巢狀一個 span 元素,該 span 元素的高和寬均為 200px,背景色為藍色。
清單 4
div.a { width:300px; height:300px; background-color:orange; } span.b { height:200px; width:200px; background-color:blue; }
分別在 IE 5 Quirks Mode 和 IE 8 Standards Mode 下執行,結果如圖 11 和 12 所示。在 Quirks Mode 下,span 元素能夠正常顯示,左圖中 200*200 的藍色的區塊。而在 Standards Mode 下,span 尺寸為零。
圖 11 IE 5 Quirks Mode
圖 12 IE 8 Standards Mode
元素的百分比高度
CSS 中對於元素的百分比高度規定如下,百分比為元素包含塊的高度,不可為負值。如果包含塊的高度沒有顯式給出,該值等同於“auto”(即取決於內容的高度)。所以百分比的高度必須在父元素有宣告高度時使用。
描述
當一個元素使用百分比高度時,在 IE Standards Mode 下,高度取決於內容的變化,而在 Quirks Mode 下,百分比高度則被正確應用。
示例展示
如下程式碼所示,為了突出顯示,我們定義一個背景為粉色的 table,在 table 的單元格中嵌入一個背景為橘色的 div b,將該 div 的高度設定為 90%。定義 b 的子節點 c 為高度和寬度均為 200px 的 div 元素,背景為藍色。
清單 5
table.a { height:500px; background-color:pink; } div.b { background-color:orange; width:300px; height:90%; display:block; } div.c { width:200px; height:200px; background-color:blue; }
分別在 IE 5 Quirks Mode 和 IE 8 Standards Mode 下執行,結果如圖 13 和 14 所示。在 Quirks Mode 下,div b 的高度為 talle 單元格的 90%,而在 Standards Mode 下,div b 的高度由其子節點 c 決定,為 200px。
圖 13 IE 5 Quirks Mode
圖 14 IE 8 Standards Mode
元素溢位的處理
CSS 中 overflow 屬性定義了一個元素的內容不適合指定的尺寸時,溢位元素內容的處理方式。預設值為 visible,即顯示溢位。
描述
在 IE Standard Mode 下,overflow 取預設值 visible,即溢位可見,這種情況下,溢位內容不會被裁剪,呈現在元素框外。而在 Quirks Mode 下,該溢位被當做擴充套件 box 來對待,即元素的大小由其內容決定,溢位不會被裁剪,元素框自動調整,包含溢位內容。
示例展示
如