瀏覽器解析模式
DOCTYPE,或者稱為 Document Type Declaration(文檔類型聲明,縮寫 DTD)。通常情況下,DOCTYPE 位於一個 HTML 文檔的最前面的位置,根元素 html 的起始標簽之前,前面沒有任何內容,不區分大小寫。因為瀏覽器必須在解析 HTML 文檔正文之前就確定當前文檔的類型,以決定其需要采用的渲染模式。不同的渲染模式會影響到瀏覽器對於 CSS 代碼甚至 JavaScript 腳本的解析。尤其是在 IE 系列瀏覽器中,由 DOCTYPE 所決定的 HTML 頁面的渲染模式至關重要。
公共 DTD,名稱格式為:註冊//組織//類型 標簽//語言,註冊指組織是否由國際標準化組織(ISO)註冊,+表示是,-表示不是。組織即組織名稱,如:W3C。類型一般是 DTD。標簽是指定公開文本描述,即對所引用的公開文本的唯一描述性名稱,後面可附帶版本號。最後語言是 DTD 語言的 ISO 639 語言標識符,如:EN 表示英文,ZH 表示中文。XHTML 1.0 可聲明三種 DTD 類型。分別表示嚴格版本,過渡版本,以及基於框架的 HTML 文檔。
當一個 HTML 文檔在沒有 DOCTYPE 時
```
CSS1CompatCSS1Compat
``` 這個頁面在所有的瀏覽器中均返回一致的結果,頁面上打印出了“BackCompat”。 document.compatMode 屬性最初由微軟在 IE 中創造出來,這是一個只讀的屬性,返回一個字符串,只可能存在兩種返回值:
- BackCompat:標準兼容模式未開啟;(混雜模式、怪異模式)
- CSS1Compat:標準兼容模式已開啟。(標註模式、嚴格模式)
值得註意的是,IE 的版本號一路從 6.0 升級,但升級僅限於標準模式。對於混雜模式,IE 的版本號永久的凍結在 5.5,這也算是為了向後兼容的巨大犧牲。也就是說即使我們使用著最新最高級的 IE9,但若我們不書寫 DOCTYPE 或者使用了能夠觸發混雜模式的 DOCTYPE,那我們所面對的瀏覽器仍相當於是那個十幾年前的老古董 IE5.5。而其他那些瀏覽器的混雜模式和標準模式之間卻沒有想 IE 中這麽大的差別。
在 html 中,docutype 有兩個主要目的:
- 對文檔進行有效性驗證。它告訴用戶代理和校驗器這個文檔是按照什麽 DTD 寫的。這個動作是被動的,每次頁面加載時,瀏覽器並不會下載 DTD 並檢查合法性,只有當手動校驗頁面時才啟用。
- 決定瀏覽器的呈現模式。對於實際操作,通知瀏覽器讀取文檔時用哪種解析算法。如果沒有寫,則瀏覽器則根據自身的規則對代碼進行解析,可能會嚴重影響 html 排版布局。
混雜模式與標準模式
不使用 DOCTYPE 一定會使 HTML 文檔處於混雜模式,然而使用了 DOCTYPE,也不一定就能夠使文檔在所有瀏覽器中均處於標準模式。這個和以下2個條件有關:
-
使用了本身就會使瀏覽器進入混雜模式的古老的甚至是錯誤的 DOCTYPE;
- 正確的 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. 字符串“>”``` 其實瀏覽器在嗅探 DOCTYPE 時只考慮了上述 6 部分中的第 1、2、4、6 部分,且不區分大小寫。如果力求最簡,則 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">。 ```
- 在 DOCTYPE 之前出現了其他內容,如註釋,甚至是 HTML 標簽
DOCTYPE 之前不能出現的內容
- 對於普通文本和 HTML 標簽,各瀏覽器均進入了混雜模式,都看到疑似的 HTML 文檔正文了,瀏覽器不太會往下追查 DOCTYPE 在哪裏。
- 對於 HTML 註釋和 XML 聲明,它們跟上面的普通文本和 HTML 標簽有些差別,它們不會在頁面中展示出來,即不可視。而有的瀏覽器則顯得十分“智能”,非 IE 瀏覽器均會忽略它們的存在,DOCTYPE 被正確解析。但是在 IE6 中,DOCTYPE 之前的 XML 聲明會導致頁面進入混雜模式,而所有的 IE 均會使 DOCTYPE 之前出現了 HTML 註釋的頁面進入混雜模式。在 IE9 中當出現這種情況時,瀏覽器在控制臺中給出了提示:“HTML1113: 文檔模式從 IE9 標準 重新啟動到 Quirks ”,看來微軟在這一點上不打算“隨大流”,這樣做也可以敦促作者盡量避免在 DOCTYPE 之前加入其他內容。
有的前端工程師很聰明,他既在 DOCTYPE 之前加入了他需要的內容,卻又沒有使 IE 由於這些內容而進入混雜模式。他可能會這麽寫:
``` <![if !IE]><![endif]> <![if false]><![endif]> 又或者是
``` 上面這些 IE 條件註釋在非 IE 瀏覽器中,可能完全被忽略,可能被解釋為普通 HTML 註釋。但是在 IE 中它們全部消失了,因為這就是 IE 條件註釋的作用。所以這也是目前比較合適的在 DOCTYPE 之前寫點什麽又保證所有瀏覽器均為標準模式的做法,但我們仍然不推薦在 DOCTYPE 之前加入任何非空白內容。
由於歷史的原因,各個瀏覽器在對頁面的渲染上存在差異,甚至同一瀏覽器在不同版本中,對頁面的渲染也不同。在W3C標準出臺以前,瀏覽器在對頁面的渲染上沒有統一規範,產生了差異(Quirks mode或者稱為Compatibility Mode);由於W3C標準的推出,瀏覽器渲染頁面有了統一的標準(CSScompat或稱為Strict mode也有叫做Standars mode),這就是二者最簡單的區別。 W3C標準推出以後,瀏覽器都開始采納新標準,但存在一個問題就是如何保證舊的網頁還能繼續瀏覽,在標準出來以前,很多頁面都是根據舊的渲染方法編寫的,如果用的標準來渲染,將導致頁面顯示異常。為保持瀏覽器渲染的兼容性,使以前的頁面能夠正常瀏覽,瀏覽器都保留了舊的渲染方法(如:微軟的IE)。這樣瀏覽器渲染上就產生了怪異模式(Quircks mode)和標準模式(Standars mode),兩種渲染方法共存在一個瀏覽器上。
火狐一直工作在標準模式下,但IE(6,7,8)標準模式與怪異模式差別很大,主要體現在對盒子模型的解釋上,這個很重要,下面就重點說這個。那麽瀏覽器究竟該采用哪種模式渲染呢?這就引出的DTD,既是網頁的頭部聲明,瀏覽器會通過識別DTD而采用相對應的渲染模式:
- 瀏覽器要使老舊的網頁正常工作,但這部分網頁是沒有doctype聲明的,所以瀏覽器對沒有doctype聲明的網頁采用quirks mode解析。
- 對於擁有doctype聲明的網頁,什麽瀏覽器采用何種模式解析,這裏有一張詳細列表可參考。
- 對於擁有doctype聲明的網頁,這裏有幾條簡單的規則可用於判斷:對於那些瀏覽器不能識別的doctype聲明,瀏覽器采用嚴格(strict mode)解析。
- 在doctype聲明中,沒有使用DTD聲明或者使用HTML4以下(不包括HTML4)的DTD聲明時,基本所有的瀏覽器都是使用quirks mode呈現,其他的則使用strict mode解析。
- 可以這麽說,在現有有doctype聲明的網頁,絕大多數是采用strict mode進行解析的。
- 在ie6中,如果在doctype聲明前有一個xml聲明(比如:<?xml version=”1.0″ encoding=”iso-8859-1″?>),則采用quirks mode解析。這條規則在ie7中已經移除了。 如何設置為怪異模式:
方法一:在頁面項部加 <!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01 Transitional//EN”>
方法二:什麽也不加。
如何設置為標準模式:
加入以下任意一種:HTML4提供了三種DOCTYPE可選擇: 1. 2. 3. 4. XHTML1.0提供了三種DOCTYPE可選擇: * 過渡型(Transitional ) * 嚴格型(Strict ) * 框架型(Frameset )
如何判定現在是標準模式還是怪異模式:
方法一:執行以下代碼
alert(window.top.document.compatMode) ;
//BackCompat 表示怪異模式
//CSS1Compat 表示標準模式
方法二:jquery為我們提供的方法,如下:
alert($.boxModel)
alert($.support.boxModel)
瀏覽器解析模式