為了處理根據web標準創作的網頁和根據在20世紀90年代末流行的陳舊實踐創作的網頁,現代的web瀏覽器實現了各種不同的引擎模式。本文說明了那些模式是什么以及如何觸發它們。
本文包括的模式轉換(mode switching)適用于firefox和其他基于gecko的瀏覽器,safari、chrome和其他基于webkit的瀏覽器,opera、 konqueror、mac版internet explorer、windows版internet explorer和內嵌ie的瀏覽器。避免提及瀏覽器引擎的名字,取而代之的是使用該引擎最知名瀏覽器的名字。
本文著重介紹模式的選擇機制,而不是記錄每個模式的確切行為。
以下是各種不同的模式:
text/html內容的模式選擇取決于doctype嗅探(doctype sniffing,本文后面有討論)。在ie8中,模式也取決于其他因素。然而在ie8的默認情況下,那些不在微軟提供黑名單上的非局域網(non- intranet)站點的模式取決于文檔類型。
再怎么強調每個瀏覽器中模式精確行為的不同也是不過分的,即使本文中進行了統一的討論。
firefox、safari、chrome和opera中,application/xhtml+xml http內容類型(不是meta元素也不是doctype!)會觸發xml模式。在xml模式中,瀏覽器嘗試給xml文檔在規范上的正確處理達到在制定瀏覽器中的程度。
ie6、7和8不支持application/xhtml+xml,mac ie5也如此。
基于webkit的nokia s60 瀏覽器中,application/xhtml+xml http內容類型不能觸發xml模式,因為在移動的圍墻花園(mobile walled gardens)中關注點是對不規范內容的兼容性。(舊式的“移動瀏覽器”無法使用真正的xml解析器,因為不規范內容已被標記為xml。)
由于沒有充分地測試konqueror,我無法確切說出在這個瀏覽器中會發生什么。
某些引擎擁有的模式與web內容無關。為了完整性,它們僅僅在這里被提到。opera有個wml2.0模式。leopard上的webkit有個用于舊式dashboard widgets的特定模式。
以下是這些模式的主要影響:
text/html的模式主要是影響css布局。例如,表格不繼承樣式是個怪癖。在某些瀏覽器的怪癖模式下,盒模型(box model)變成ie5.5的盒模型。本文檔沒有列舉出所有的布局怪癖。
準標準模式(有這種模式的瀏覽器中)中,僅包含圖片的表格單元格的高和標準模式中不同。
xml模式中,選擇器有不同的區分大小寫行為。此外,用于html body元素的特有規則不能應用在那些沒有實現最新css2.1改變的較舊版本的瀏覽器。
也有一些怪癖影響html和css的解析且會導致符合標準的網頁被錯誤解析。怪癖布局決定了這些怪癖是否開啟。無論如何,了解怪癖模式和標準模式在css布局和解析(非html解析)上的主要異同是非常重要的。
一些人錯誤地把標準模式稱為“嚴格解析模式(strict parsing mode)”,其讓人誤解了瀏覽器強制執行html語法規則和用瀏覽器評估標記的正確性。情況并非如此。即使當標準模式布局生效時,瀏覽器依舊會做標簽雜燴湯(tag soup,http://en.wikipedia.org/wiki/tag_soup)修正工作。(在2000年netscape6發布前,mozilla的確有用于強制執行html語法規則的解析模式。這些模式和現有的web內容不兼容而被遺棄。)
另一個常見的誤解是關于xhtml解析的。通常認為用xhtml doctype得到不同的解析。其實并非如此,內容類型是text/html的xhtml文檔所用解析器和html文檔的是同一個。目前瀏覽器在意的是文檔類型為text/html的xhtml僅是“撒面包丁的標簽雜燴湯(tag soup with croutons)”(到處是額外的斜線)。
僅當使用xml文檔類型的文檔(例如:application/xhtml+xml或xmapplication/)會觸發xml模式來解析,這時的解析器完全不同于html解析器。
雖然怪癖模式主要是關于css的,但也有一些是關于腳本的。例如,firefox的怪癖模式中,html id 屬性像在ie一樣建立了全局腳本作用域的對象引用。ie8中關于腳本的影響比其他瀏覽器更值得關注。
xml模式中,某些dom api的行為徹底不同,因為xml的dom api行為被定義時不兼容html的行為。
現代瀏覽器使用doctype嗅探來決定text/html文檔的引擎模式。這意味著模式的選擇是基于html文檔開始的文檔類型聲明(或缺少)。(這不適于使用xml文檔類型的文檔。)
文檔類型聲明(doctype)是sgml的語法偽造,sgml是個舊式的標記框架,html5之前的html就是依據其定義的。html4.01規范中,文檔類型聲明描述的是html的版本信息。盡管名字叫“文檔類型聲明”且html 4.01規范所描述的是關于“版本信息”,文檔類型聲明并不適用把sgml或xml文檔分類為特定類型的文檔,即使它看起來像是(因為名字)。(更多內容在附錄中)
html4.01規范和iso 8879(sgml)都沒有說關于使用文檔類型聲明作為引擎模式轉換的任何事情。doctype嗅探是基于觀察,在doctype嗅探被設計時,絕大部分的怪癖文檔既沒有文檔類型聲明也沒有引用舊的dtd。html5接受這個事實,且定義了text/html中doctype作為唯一的模式轉換。
典型的預html5(pre-html5)文檔類型聲明包含(被空白分開)“<!doctype”字符串,根元素(“html”)的通用標識符, “public”字符串,處于引號中的dtd公共標識符,同一dtd的可能系統標識符(url)和字符 “>”。文檔類型聲明位于文檔的根元素開始標簽之前。
下面是創建新的text/html文檔時如何選擇doctype的簡單指南:
我不推薦任何的xhtml doctype,因為xhtml被用作text/html被認為是有害的。無論如何,如果你選擇使用xhtml doctype,請注意xml聲明會使ie6(但不是ie7?。┯|發怪癖模式。
對application/xhtml+xml的簡單指南是絕不使用doctype。該方式下的網頁不是“嚴格一致”的xhmtl1.0,但這并不重要。(請看后面的附錄)
a list apart 曾介紹 ,ie8除doctype外會使用基于meta元素的模式轉換作為模式選擇的因素之一。(請看ian hickson、david baron、david baron again、robert o’callahan 和 maciej stachowiak的評論。)
ie8有4種模式:ie5.5怪癖模式、ie7標準模式、ie8 準標準模式 和ie8標準模式。模式的選擇取決于來自幾個方面的數據:doctype、meta元素、http頭、來自微軟的定期下載數據、局域網域、用戶所做設置、局域網管理員所做設置、父框架的模式(如果有)和地址欄兼容視圖按鈕被用戶觸發。(對于嵌入該引擎的其他應用,模式也取決于嵌入的應用。)
幸運的是如果出現下列情況,ie8大體上會像其他瀏覽器一樣使用doctype嗅探:
上述除兩個關于x-ua-compatible的情況外,ie8像ie7一樣執行doctype嗅探。ie7仿真( ie7 emulation)叫兼容視圖。
在 x-ua-compatible 情況下,ie8的行為和其他瀏覽器完全不同。想看本頁的附錄或pdf和png格式的流程圖。
不幸的是,沒有 x-ua-compatible的http頭或meta標簽,即使使用了合適的doctype,ie8讓用戶無意間使頁面從ie8的標準模式降到ie7模式,這是一種仿真的ie7標準模式。更糟糕的是,局域網管理員也可以這么做。微軟也可以把你所用的所有域名到列入黑名單。
為了對付這些影響,doctype是不夠的,你需要x-ua-compatible http頭和meta標簽。
下面的簡單指南是針對已經有doctype在其他瀏覽器觸發標準模式或者準標準模式的新的text/html文檔如何選擇x-ua-compatible http頭或meta標簽的:
請不要把doctype嗅探帶到xml。
doctype嗅探是用簽雜燴湯似的方法解決一個標簽雜燴湯問題。doctype嗅探是在html4和css2規范發布后設計的一種試探方法,它從文檔中區分出過時文檔以符合其作者可能期望的行為。
偶爾有人建議在xml上使用doctype嗅探來調度不同的處理、識別正在使用的詞匯表或激活特性。這是個壞主意。調度和詞匯表識別應該是基于名字空間的,而特性激活應該是基于明確的處理指令或元素。
良構(well-formedness)的整個思想是介紹允許xml的無dtd解析,且推廣無doctype文檔。在正式情況下,兩個xml文檔有相同的規范形式且應用不同地處理它們(且不同之處并非因為沒有選擇處理外部實體),這個應用或許被破壞了。在實踐情況下,如果兩個xml文檔導致同樣的內容被報告(qnames忽略)給sax2內容處理器且應用不同地處理文檔,這個應用或者被破壞了??紤]到作為 web作者無法相信每個人都會使用解決額外實體的xmlprocessor來解析其頁面(即使一些瀏覽器看起來這樣做,因為它們會映射一定公共的標識符到一個有刪節的定義實體的dtd),插入doctype到xml中用于web是毫無意義的且通常會導致貨運崇拜(cargo cultish)習慣。(您仍然使用w3c驗證器的dtd覆蓋功能來對一個dtd進行驗證,雖然w3c驗證器會說結果僅僅是暫時有效?;蚋玫氖?,你可以用放寬ng驗證,它不會污染模式引用的文檔。)為了嗅探而要求doctype是非常愚蠢的,即使那是在html實踐中的解決方法。
此外,當低級別的規范定義兩個相等的東西時,高級別的規范不應該嘗試給它們不同的含義。請考慮<!doctype html public "-//w3c//dtd xhtml 1.0 strict//en" "http://www.w3.org/tr/xhtml1/dtd/xhtml1-strict.dtd">。如果刪除公共標識符,依舊指定了同樣的dtd,因此doctype <!doctype html system "http://www.w3.org/tr/xhtml1/dtd/xhtml1-strict.dtd">表示和前面的doctype一樣。應該不同地嗅探它們么?可以進一步理論。假設復制給example.com一個叫foobar.dtd的dtd:<!doctype html system "http://example.com/foobar.dtd">。這該如何嗅探?應該是同一個意思。甚至整個dtd可以貼在文檔中。
換句話說,如果有#include “foo.h”,你不應該給名字foo.h綁定任何black magic,因為它應該允許復制foo.h的內容到文檔中或復制foo.h到bar.h中且表示#include “bar.h”。
我不擔心html和sgml構造相同的參數的原因是web瀏覽器不會使用真正的sgml解析器去解析html,所以我認為偽裝成sgml進行處理是沒有用的。無論如何,如果你還不相信,請看w. eliot kimber關于此事的文章 comp.text.sgml
下表中,怪癖模式、標準模式和準標準分別表示為q、s和a。當瀏覽器僅有兩種模式時,如果表格單元格的行高和mozilla的標準模式表現一致時,標準模式標記為“s”,如果表格單元格的行高和mozilla的準標準模式表現一致時,則標記為“a”。
請注意使用xml內容模型提供服務的xhtml在xml模式下渲染。
本表的目的并不是說表中所有的doctype都是新建頁面的合理選擇。本表的目的是為了展示我的推薦是依據什么樣的數據。
下列的簡寫符號是用于列標題:
doctype | ns6 | old moz | moz & safari & opera10 & html5 | opera9.0 | ie8 & opera9.5 | ie7 & opera7.10 | ie6 & opera7.0 | mac ie5 | konq3.2 |
---|---|---|---|---|---|---|---|---|---|
none | q | q | q | q | q | q | q | q | q |
<!doctype html public "-//w3c//dtd html 3.2 final//en"> | q | q | q | q | q | q | q | q | q |
<!doctype html public "-//w3c//dtd html 4.0//en"> | s | s | s | s | s | a | a | a | a |
<!doctype html public "-//w3c//dtd html 4.01//en"> | s | s | s | s | s | a | a | q | a |
<!doctype html public "-//w3c//dtd html 4.0//en" "http://www.w3.org/tr/html4/strict.dtd"> | s | s | s | s | s | a | a | a | a |
<!doctype html public "-//w3c//dtd html 4.01//en" "http://www.w3.org/tr/html4/strict.dtd"> | s | s | s | s | s | a | a | a | a |
<!doctype html public "-//w3c//dtd html 4.0 transitional//en"> | q | q | q | q | q | q | q | q | q |
<!doctype html public "-//w3c//dtd html 4.01 transitional//en"> | q | q | q | q | q | q | q | q | q |
<!doctype html public "-//w3c//dtd html 4.01 transitional//en" "http://www.w3.org/tr/html4/loose.dtd"> | s | s | a | a | a | a | a | a | q |
<!doctype html public "-//w3c//dtd html 4.01 transitional//en" "http://www.w3.org/tr/1999/rec-html401-19991224/loose.dtd">
| q | s | a | a | a | a | a | a | q |
<!doctype html public "-//w3c//dtd html 4.0 transitional//en" "http://www.w3.org/tr/html4/loose.dtd"> | q | q | q | q | a | a | a | a | q |
<!doctype html public "-//w3c//dtd xhtml 1.1//en" "http://www.w3.org/tr/xhtml11/dtd/xhtml11.dtd"> | s | s | s | s | s | a | a | a | a |
<!doctype html public "-//w3c//dtd xhtml basic 1.0//en" "http://www.w3.org/tr/xhtml-basic/xhtml-basic10.dtd"> | s | s | s | s | s | a | a | a | a |
<!doctype html public "-//w3c//dtd xhtml 1.0 strict//en" "http://www.w3.org/tr/xhtml1/dtd/xhtml1-strict.dtd"> | s | s | s | s | s | a | a | a | a |
<!doctype html public "-//w3c//dtd xhtml 1.0 transitional//en" "http://www.w3.org/tr/xhtml1/dtd/xhtml1-transitional.dtd"> | s | s | a | a | a | a | a | a | q |
<?xml version="1.0" encoding="utf-8"?> <!doctype html public "-//w3c//dtd xhtml 1.1//en" "http://www.w3.org/tr/xhtml11/dtd/xhtml11.dtd"> | s | s | s | s | s | a | q | a | q |
<?xml version="1.0" encoding="utf-8"?> <!doctype html public "-//w3c//dtd xhtml basic 1.0//en" "http://www.w3.org/tr/xhtml-basic/xhtml-basic10.dtd"> | s | s | s | s | s | a | q | a | q |
<?xml version="1.0" encoding="utf-8"?> <!doctype html public "-//w3c//dtd xhtml 1.0 strict//en" "http://www.w3.org/tr/xhtml1/dtd/xhtml1-strict.dtd"> | s | s | s | s | s | a | q | a | q |
<?xml version="1.0" encoding="utf-8"?> <!doctype html public "-//w3c//dtd xhtml 1.0 transitional//en" "http://www.w3.org/tr/xhtml1/dtd/xhtml1-transitional.dtd">
| s | s | a | a | a | a | q | a | q |
<!doctype html public "iso/iec 15445:2000//dtd html//en"> | q | s | s | q | q | q | q | q | q |
<!doctype html public "iso/iec 15445:2000//dtd hypertext markup language//en"> | q | s | s | s | s | a | a | a | q |
<!doctype html public "iso/iec 15445:1999//dtd html//en"> | s | s | s | q | q | q | q | q | q |
<!doctype html public "iso/iec 15445:1999//dtd hypertext markup language//en"> | s | s | s | s | s | a | a | a | q |
<!doctype html> | q | s | s | s | s | a | a | a |
moziila的doctype嗅探代碼在2000年10月、2001年9月和2002年6月有大幅度的修改。本文檔描述的mozilla(和 netscape 6.x)建立的狀態可以自2000.10.19起在ftp.mozilla.org上看到。本文檔未涉及mozilla m18(和netscape 6.0 pr3)中的doctype嗅探的工作方式。safari的doctype嗅探代碼自第一個公開的測試版起也有大幅度的修改。本文檔不包括比版本v73也叫0.9更早的行為。
konqueror3.5之前的doctype嗅探代碼似乎來自于safari的很早的一個版本。konqueror現在和safari匹配,其doctype嗅探代碼來自mozilla。
從表中可見,opera的doctype嗅探正由規律的從類似ie向類似mozilla轉變,雖然opera9.5和9.6在倒退的路上。同時,opera怪癖模式的布局行為已從仿效ie6的怪癖模式轉換到mozilla的怪癖模式。
這些步驟都可以通過pdf和png格式的流程圖看到。
感謝simon pieters、simon pieters和anne van kesteren幫助我改正了各種opera版本的模式表和他們的評論。感謝simon pieters制作了另一份ie8的流程圖。
新聞熱點
疑難解答