DOCTYPE 與瀏覽器渲染模式分析

DOCTYPE 的誕生

DOCTYPE,或者稱爲 Document Type Declaration(文檔類型聲明,縮寫 DTD)。通常情況下,DOCTYPE 位於一個 HTML 文檔的最前面的位置,位於根元素 HTML 的起始標籤之前。因爲瀏覽器必須在解析 HTML 文檔正文之前就確定當前文檔的類型,以決定其需要採用的渲染模式,不同的渲染模式會影響到瀏覽器對於 CSS 代碼甚至 JavaScript 腳本的解析。尤其是在 IE 系列瀏覽器中,由 DOCTYPE 所決定的 HTML 頁面的渲染模式至關重要。

首先看看當一個 HTML 文檔在沒有 DOCTYPE 時,頁面在各瀏覽器中會如何渲染及解析。我們嘗試生成一個在最頂端沒有 DOCTYPE 的 HTML 文檔:

<html>
<head></head>
<body>
<script>
document.write(document.compatMode);
</script>
</body>
</html>

這個頁面在所有的瀏覽器中均返回一致的結果,頁面上打印出了“BackCompat”。 document.compatMode 屬性最初由微軟在 IE 中創造出來,這是一個只讀的屬性,返回一個字符串,只可能存在兩種返回值:

  • BackCompat:標準兼容模式(Standards-compliant mode)未開啓;
  • CSS1Compat:標準兼容模式已開啓。

其實這裏所謂的標準兼容模式未開啓即“混雜模式”(又叫怪異模式,Quirks mode),標準兼容模式已開啓即“標準模式”(又叫嚴格模式,Standards mode 或者 Strict mode)。 所以前面那個測試樣例中,沒有書寫 DOCTYPE 的 HTML 文檔在所有瀏覽器中均會以混雜模式進行渲染和解析。

注:document.compatMode 在 MSDN 中的介紹:compatMode Property

究竟爲何瀏覽器要製作這麼一個“開關”。微軟開發的 IE 系列瀏覽器中壽命最長的 IE6 伴隨 Windows XP 誕生。相比上一個版本 IE5.5,IE6 確實有着許多重大的改進,其中對於頁面渲染而言最大的變化就在於 IE6 支持了部分 CSS1 中的特性。例如,爲一個塊級元素設定寬度及高度時,不再作用於 border 外圍,而是如 W3C 規範中所描述的僅僅是元素內容之上。這一點和 IE5.5 差別巨大。爲了保證那些 90 年代後期的基於 IE6 之前版本開發的頁面能夠正常顯示,即保證瀏覽器有向後兼容性,此“開關”誕生,微軟試圖通過對 DOCTYPE 的判斷來決定瀏覽器採取何種模式工作,即是 IE6 還是 IE5.5 的問題。所以從 document.compatMode 返回的字符串值中也可以看出來,BackCompat 代表了向後兼容(即 IE5.5),CSS1Compat 代表了對 CSS1 規範的兼容(即 IE6)。由此,瀏覽器的工作模式被分爲了混雜模式及標準模式。

值得注意的是,IE 的版本號一路從 6.0 升至了目前的 9.0,但升級僅限於標準模式。對於混雜模式,IE 的版本號永久的凍結在 5.5,這也算是爲了向後兼容的巨大犧牲。也就是說即使我們使用着最新最高級的 IE9,但若我們不書寫 DOCTYPE 或者使用了能夠觸發混雜模式的 DOCTYPE,那我們所面對的瀏覽器仍相當於是那個十幾年前的老古董 IE5.5。而其他那些瀏覽器的混雜模式和標準模式之間卻沒有想 IE 中這麼大的差別。

注:IE6 增強的 CSS:CSS Enhancements in Internet Explorer 6

近似標準模式

近似標準模式(Almost Standards Mode)從字面意思上看與標準模式非常類似,但確實有小的差別。主要體現在對於表格單元格內垂直方向佈局渲染差異。IE8 開始、Firefox、Chrome、Safari、Opera 7.5 開始,這些瀏覽器的標準模式更加嚴格的遵循了 CSS2.1 規範,故對於在目前看來不太“標準”的以前的標準模式,被賦予了“近似標準模式”的名字。但是在較早的 IE6 IE7 以及 Opera 7.5 之前版本中,瀏覽器無法嚴格遵循 CSS2.1 規範,故對於它們來說沒有這個近似標準模式,也可以理解爲它們的近似標準模式就是標準模式。

到目前爲止,可以看到各瀏覽器主要包含了三種模式。在 HTML5 草案中,更加明確的規定了模式的定義:

傳統名稱 HTML5 草案名稱 document.compatMode 返回值
standards mode 或者 strict mode no-quirks mode CSS1Compat
almost standards mode limited-quirks mode CSS1Compat
quirks mode quirks mode BackCompat

注:HTML5 草案關於 compatMode 的介紹:3.1.3 Resource metadata management

DOCTYPE 的選擇

工作模式簡介

瀏覽器的工作模式常被稱爲“渲染模式”。實際上瀏覽器不同的工作模式不僅對渲染有影響,對代碼的解析以及腳本的行爲也同樣有影響。

從更廣泛的角度來看,瀏覽器的工作模式的差異不僅體現在處理 HTML 頁面的時候,處理 XML 及一些非 WEB 內容時也有模式上的差異,但本文僅討論瀏覽器在處理 HTML 頁面時工作模式。1

注:

  1. 關於瀏覽器的工作模式的更多信息,請參考 Activating Browser Modes with Doctype

工作模式的來源及變遷

不使用 DOCTYPE 一定會使 HTML 文檔處於混雜模式,然而使用了 DOCTYPE,也不一定就能夠使文檔在所有瀏覽器中均處於標準模式。DOCTYPE 本身不就是一個“開關”嗎?爲何在有 DOCTYPE 的 HTML 文檔之上仍然還會出現混雜模式?這個和以下條件有關:

  • 使用了本身就會使瀏覽器進入混雜模式的古老的甚至是錯誤的 DOCTYPE;
  • 在 DOCTYPE 之前出現了其他內容,如註釋,甚至是 HTML 標籤。

我們先說第一個條件。HTML 歷史悠久,僅正確的 HTML 類型的 DOCTYPE 就有很多種。先看一個標準的 DOCTYPE:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

上面的 DOCTYPE 包含 6 部分:

  1. 字符串“<!DOCTYPE”
  2. 根元素通用標識符“HTML”
  3. 字符串“PUBLIC”
  4. 被引號括起來的公共標識符(publicId)“-//W3C//DTD HTML 4.01//EN”
  5. 被引號括起來的系統標識符(systemId)“http://www.w3.org/TR/html4/strict.dtd”
  6. 字符串“>”

其中根元素通用標識符、公共標識符、系統標識符均可以通過腳本調用 DOM 接口獲得,分別對應 document.doctype.name、document.doctype.publicId、document.doctype.systemId(IE6 IE7 不支持)。

不同的 DOCTYPE 之間,上面三部分可能不盡相同,有些 DOCTYPE 確實其中某部分,如何在這些紛繁的 DOCTYPE 中選擇?

其實瀏覽器在嗅探 DOCTYPE 時只考慮了上述 6 部分中的第 1、2、4、6 部分,且不區分大小寫。在各瀏覽器內核實現中,幾乎都存在一個名單用於記錄這些常見的 DOCTYPE 所對應的模式,例如 WebKit 內核中 DocTypeStrings.gperf 文件。各瀏覽器名單列表中觸發模式的不同導致了某些 DOCTYPE 出現在不同瀏覽器中觸發了不同模式的現象,如 。而對於名單之外的 DOCTYPE,瀏覽器之間處理的差異也會導致觸發不同的模式,比如可能有的瀏覽器會將名單之外的 DOCTYPE 當作混雜模式,而有的卻會一律當作標準模式。

所以我們在選用 DOCTYPE 的時候首先確定的是我們想讓 HTML 文檔使用標準模式。

如果力求最簡,則 HTML5 的 DOCTYPE 是最佳選擇:<!DOCTYPE html>,所有的主流瀏覽器均將這種只包含第 1、2、6 部分的最短的 DOCTYPE 視爲標準模式。

如果力求穩妥,則較早的 HTML4.01 Strict 的 DOCTYPE 也是一種好的選擇:<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">,它在各主流瀏覽器中觸發的模式與上面的 HTML5 的完全一致。

有時候我們處於特殊情況也希望瀏覽器能夠都處於近似標準模式,則可選擇:<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">。

注:關於 Firefox 中 DTD 與瀏覽器工作模式:Mozilla's DOCTYPE sniffing

DOCTYPE 之前不能出現的內容

前面提到,DOCTYPE 作爲一個決定瀏覽器對於 HTML 文檔採取何種模式“開關”,應出現在 HTML 文檔的最前面。但有時候處於某些原因,有的作者會在 DOCTYPE 之前防止一些內容,可能是服務端輸出的某些信息。這樣會讓瀏覽器感到極爲“困惑”,它第一眼看到的不是 DOCTYPE,故可能會認爲頁面沒有 DOCTYPE,則可能觸發了混雜模式。然而事實上在這一點各瀏覽器的處理並不相同。我們將 DOCTYPE 之前可能出現的這些內容分類,它們包括:

  • 普通文本
  • HTML 標籤
  • HTML 註釋
  • XML 聲明
  • IE 條件註釋

對於普通文本和 HTML 標籤,各瀏覽器均進入了混雜模式,這個很好理解,都看到疑似的 HTML 文檔正文了,瀏覽器不太會往下追查 DOCTYPE 在哪裏。

對於 HTML 註釋和 XML 聲明,它們和上面的普通文本和 HTML 標籤有些差別,它們不會在頁面中展示出來,即不可視。這時,有的瀏覽器則顯得十分“智能”,非 IE 瀏覽器均會忽略它們的存在,DOCTYPE 被正確解析。但是在 IE6 中,DOCTYPE 之前的 XML 聲明會導致頁面進入混雜模式,而所有的 IE 均會使 DOCTYPE 之前出現了 HTML 註釋的頁面進入混雜模式。在 IE9 中當出現這種情況時,瀏覽器在控制檯中給出了提示:“HTML1113: 文檔模式從 IE9 標準 重新啓動到 Quirks ”,看來微軟在這一點上不打算“隨大流”,這樣做也可以敦促作者儘量避免在 DOCTYPE 之前加入其他內容。

有的作者很聰明,他既在 DOCTYPE 之前加入了他需要的內容,卻又沒有使 IE 由於這些內容而進入混雜模式。他可能會這麼寫:

  • <![if !IE]><!-- some comments --><![endif]>
  • <![if false]><!-- some comments --><![endif]>

又或者是

  • <!--[if !IE]>some text<![endif]-->

上面這些 IE 條件註釋在非 IE 瀏覽器中,可能完全被忽略,可能被解釋爲普通 HTML 註釋。但是在 IE 中它們全部消失了,因爲這就是 IE 條件註釋的作用。所以這也是目前比較合適的在 DOCTYPE 之前寫點什麼又保證所有瀏覽器均爲標準模式的做法,但我們仍然不推薦在 DOCTYPE 之前加入任何非空白內容。

注:關於 IE 條件註釋:About Conditional Comments

建議

通過上面的歷史回顧以及分析,我們看到了 DOCTYPE 對於目前主流瀏覽器的關鍵作用,同時也發掘了能夠觸發各瀏覽器標準模式的最佳 DOCTYPE。標準模式會使不同瀏覽器之間發生兼容性問題的風險降至最低,選擇正確的 DOCTYPE 以及保證 DOCTYPE 在 HTML 文檔中絕對開頭的位置則是使 DOCTYPE 發揮其正確作用的關鍵。

測試環境

操作系統版本: Windows 7 Ultimate build 7600
瀏覽器版本: IE6
IE7
IE8
IE9
Firefox 4.0.1
Chrome 12.0.742.100
Safari 5.0.5
Opera 11.11
測試頁面:  
本文更新時間: 2011-06-17

關鍵字

瀏覽器 兼容性 渲染模式 標準模式 混雜模式 DOCTYPE DTD

轉載自:
http://w3help.org/zh-cn/casestudies/002
 
發佈了16 篇原創文章 · 獲贊 11 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章