翻譯自《The Internet Explorer hasLayout Property》
http://jmedia.cn/
在一個完美的世界,我們不需要知道hasLayout屬性是什麼東西。它是Windows Internet Explorer渲染引擎的一個內部組成部分。但是它的作用不可小覷,他對元素的外觀和行為有很大影響,主要針對元素內容的約束和與鄰接元素的相互作用。
這篇文章完全針對Windows的Internet Explorer。
hasLayout屬性是什嗎?
在Internet Explorer中,一個元素要麼自己對自身的內容進行計算大小和組織,要麼依賴於父元素來計算尺寸和組織內容。
為了調節這兩個不同的概念,渲染引擎採用了所謂的hasLayout的屬性,屬性值可以為true或false。當一個元素的hasLayout屬性值為true時,我們說這個元素有一個布局(layout)。1
當一個元素有一個布局時,它負責對自己和可能的子孫元素進行尺寸計算和定位。2 簡單來說,這意味著這個元素需要花更多的代價來維護自身和裡面的內容,而不是依賴於祖先元素來完成這些工作。因此,一些元素預設會有一個布局,儘管大多數都沒有。
負責組織自身內容的元素將預設有一個布局,主要包括以下元素(不完全列表):
- body and html (in standards mode)
- table, tr, th, td
- img
- hr
- input, button, file, select, textarea, fieldset
- marquee
- frameset, frame, iframe
- objects, applets, embed
對於並非所有的元素都預設有布局,微軟給出的主要原因是“效能和簡潔”。如果所有的元素都預設有布局,會對效能和記憶體使用量上產生有害的影響。
那麼,我們為什麼要關心這個hasLayout屬性呢?原因是,許多Internet Explorer的顯示不一致問題,都可以歸因於這個屬性。
在大多數情況下,有與元素缺少布局而導致的問題很容易發現:內容往往錯位了或者完全不見了。例如,當一個元素(如div,它預設情況下是沒有布局的)內含浮動或絕對位置的內容時,它通常會表現出奇怪和錯誤的行為。這類可能產生的奇怪行為是多種多樣的,包括內容缺失或者錯位,或者當瀏覽器視窗移動或者滾動時元素重繪失敗。3
如果你發現一塊內容有的顯示有點不顯示,部分網頁只顯示了部分內容,這些跡象都表明很可能某個元素需要一個布局。當關鍵元素有了布局以後,這個問題就會奇蹟般地消失了。事實上,在日常開發中所遇到的99%的Internet Explorer CSS的bug都可以用設定hasLayout的方法來修正。修正hasLayout具體無非聲明一個CSS屬性來使這個因素獲得布局,如果這個元素預設沒有布局的話。
為一個元素設定布局最簡單的方法是,設定一個CSS尺寸屬性(例如,寬度width或高度height)。然而,有些情況下你可能不希望對元素設定具體的寬度或高度,還有其他一些的CSS屬性也可以達到相同的效果。
這些其他屬性是:
- display: inline-block
- height: (任何值除了auto)
- float: (left 或 right)
- position: absolute
- width: (任何值除了auto)
- writing-mode: tb-rl
- zoom: (任何值除了normal)4
Internet Explorer 7還有一些額外的屬性(不完全列表) :
- min-height: (任何值)
- max-height: (任何值除了none)
- min-width: (任何值)
- max-width: (任何值除了none)
- overflow: (任何值除了visible)
- overflow-x: (任何值除了visible)
- overflow-y: (任何值除了visible)5
- position: fixed
聲明任何這些CSS屬性都會讓元素得到布局,當然前提是這個屬性對這個元素是有效。例如,我們不能對內嵌(inline)元素設定高度,除非文檔運行於quirks mode。
讓所有的元素都有布局並不明智——不僅是因為前面提到的對效能和記憶體的問題,還因為許多其他不必要的CSS副作用會發生。例如:
- 絕對位置或者浮動元素的子孫元素有布局時,就不會收縮環繞其中的內容。
- 浮動元素旁的靜態定位內容不會環繞浮動元素,而是形成一個矩形塊並列在浮動元素旁。 更多的例子可以在MSDN網站上找到。
hasLayout問題的調試
如果您發現您的網頁在Internet Explorer中表現奇怪,可以嘗試為一個元素設定一個CSS屬性來得到布局,看看問題是否消失。 對於設定哪個元素是有些技巧可言的。隨著經驗的增加,很容易就可以確定。通常是一個沒有明確設定寬度的父容器,或者其寬度只定義了外邊距(margin)。如果這個父元素包含浮動或絕對位置的元素,它可能就是造成問題的原因。如果父物件考慮到維護子物件的問題,那麼問題就可能會產生。
有一個有用的辦法來調試布局的問題,對文檔中的元素逐個設定CSS屬性zoom為1來隔離產生問題的元素。如果你對某個元素設定了這個屬性,然後問題解決了,那麼你就成功了。屬性zoom很有用,因為它不僅能夠觸發元素獲得布局,而且在大多數情況下,設定這個屬性不會改變網頁的顯示(除了你正在修複的這個bug),而其他方式就可能會 。這個排除法可以很快找到問題所在。
一旦你找到了產生問題的元素,你就可以進行必要的修正了。最好的辦法是對這個元素設定一個或多個CSS的尺寸屬性。但是,在不能正常應用尺寸屬性的情況下,就只能尋找替代方案了。
對於Internet Explorer 7 ,最好的辦法是設定最小高度屬性為0;這個技術是無害的,因為0本來就是這個屬性的初始值。而且沒有必要對其他瀏覽器隱藏這個屬性,但對於我們的下一個建議就不是這樣了!
而對於Internet Explorer 6和更早版本中觸發一個元素得到布局的標準方法是設定這個元素的高度屬性為1%,只要overflow屬性沒有被設定過(除了visible)。這種方法利用了這些版本瀏覽器的一個bug,即如果overflow屬性設定為預設值visible,包含的盒子的高度會自動根據裡面的內容擴大而忽略原始的高度值。不過,大多數其他瀏覽器將尊重高度值1%,而你通常不要他們這樣做,所以這項聲明需要對所有其他的瀏覽器隱藏。
在過去幾年裡,這個設定高度為1%且僅對Internet Explorer 6和早期版本可見的技術,被稱為霍莉破解(Holly hack)。現在,僅對Internet Explorer進行CSS聲明的推薦方法是通過利用條件注釋來做。
好訊息是,Internet Explorer 7比以前的版本要健全很多,許多(儘管不幸不是所有的)和布局有關的問題已經消失了,相比以前的版本瀏覽器,你會需要少得多的修複。如需關於布局問題的更多資訊,請參見Satzansatz網站的“關於布局”。
腳註
1 一旦一個元素有了布局,它的hasLayout屬性就可以被渲染引擎和指令碼查詢到。
2 如果一個子孫元素也有布局,它會處理自身及其子孫元素的尺寸計算,但是它的定位是由它的父元素決定的。
3 關於這些行為的幾個例子的詳細描述可以在Position Is Everything網站找到,網址是http://positioniseverything.net/explorer.html。
4 屬性zoom和writing-mode是Internet Explorer專有的CSS屬性,所以使用了會通不過CSS合法驗證。
5 overflow-x and overflow-y是CSS3的提議屬性, 但從Internet Explorer 5就已經有了。