網頁制作Poluoluo文章簡介:Firefox Bug: inline/inline-block的間隙.
首先要說明的是,這個標題有點標題黨的意思,這個 bug 也存在於 IE8 下,在 IE6 和 IE7 下正常。之前寫過兩篇關於 IE bug 的文章,這裡特意用了 Firefox bug 作為標題,是為了給自己找點心裡安慰,省得總是埋怨 IE :)。
關於 inline-block,可以參考之前的一篇文章 跨浏覽器的inline-block:
啊,inline-block,挺難琢磨並且迷人的聲明上承諾了很多,其實提供了很少。很多次我拿到類似這樣的 PSD 文件:
就哭了。
一般說來,這種類型的布局是小菜一樁。固定寬度,固定高度,向左浮動就解決了。但是,這個設計中內容的多少是可變的,這就意味著如果這些塊中的一些內容比其他的多,就會破壞這個布局。
因為第一個展示項比其他項高,第五個項目就相對第一個浮動,而不是位於它下面了。基本上我們想要一個彈性表格的布局,但是適當的,語義標記。
我們以一個無序列表開始這個簡單的頁面,並把 display 設置為 inline-block:
<ul> <li> <h4>This is awesome</h4> <img src="http://farm4.static.flickr.com/3623/3279671785_d1f2e665b6_s.jpg" alt="lobster" width="75" height="75" /></li> ...</ul>
<!-- li { width: 200px; min-height: 250px; border: 1px solid #000; display: inline-block; margin: 5px; } -->
效果在 Firefox 3, Safari 3 和 opera 中看起來沒問題:
顯然,在垂直排列上有些錯誤。嗯,也不算錯誤吧,這是正確的表現,只不過不是我們想要的效果。
這是因為每個 <li> 元素的基線是和其父元素 <ul> 的基線對齊排列的。你要問啥是基線?一圖頂千言那:
基線就是橫貫上面文本的黑線。盡量說的簡單點。inline 或者 inline-block 元素默認的 vertical-align 值 就是基線。也就是說元素基線要和她父元素的基線對齊。下面有一個示例:
就如所看到的,每個基線都是和文本 ‘This is the baseline.’ 的基線對齊的。文本雖然不在 <li> 內部,但是文本節點的父元素 <ul> 就指出了父元素的基線所在。
總之,修正方法是很簡單的: vertical-align: top,這樣就能得到一個看起來不錯阿網格:
但是在 Firefox 2, IE 6 和 7 中,依然無效:
從 Firefox 2 入手。
Firefox 2 不支持 inline-block,但是它支持 Mozilla 特有的顯示屬性 ‘-moz-inline-stack’,這個屬性和 inline-block 比較像。把它加在 display: inline-block 之前,FF2 會忽略 inline-block 而保留 -moz-inline-stack,因為它不認識 inline-block。支持 inline-block 的浏覽器會使用 inline-block 而忽略之前的顯示屬性。
li { width: 200px; min-height: 250px; border: 1px solid #000; display: -moz-inline-stack; display: inline-block; vertical-align: top; margin: 5px; }
不幸的是,有點小bug:
坦白地說,我不知道什麼導致了這個 bug。但是有個快速的修正方法。把 <li> 中所有的東西用 <div> 包含起來。
<li> <div> <h4>This is awesome</h4> <img src="http://farm4.static.flickr.com/3623/3279671785_d1f2e665b6_s.jpg" alt="lobster" width="75" height="75" /></div></li>
貌似 <li> 中的內容被’重置’並且正確顯示了。
2009.04.29更新:經過多方查證,嵌套div的方法可以解釋為:FF對於所有的屬性為stack(當然保持-moz-inline-stack)的元素,它的第一級子元素會繼承該元素的寬度和高度,但是子元素的子元素就不會再繼承其寬和高了。不過,其實,FF2在某種程度上可以無視了……——by 神飛
現在,轉到 IE 7 上來。IE 7 也不支持 inline-block,但是我們可以欺騙它以使 <li> 好像是 inline-block 的。怎麼做呢?hasLayout,IE 的一個帶來樂趣的神奇屬性。你無法在一個元素上用 hasLayout: true; 顯示地設置 hasLayout,或通過其他類似的簡單方法,但是可以用其他類似 zoom:1 的聲明來激發它。
技術上來說,hasLayout 意味著,一個 hasLayout 設為 true 的元素負責渲染它自己及其子元素(把它和 min-height 和 width 聯合起來,就得到了和 display:block 非常相似的效果)。這有點像神奇的精靈粉,把它灑在渲染問題上,問題就消失了。
當我們給 <li> 加上 zoom:1 和 *display:inline(用於 IE6 和 IE7 的星號 hack) 之後,在 IE7 中它們就可以像 inline-block 一樣顯示了:
li { width: 200px; min-height: 250px; border: 1px solid #000; display: -moz-inline-stack; display: inline-block; vertical-align: top; margin: 5px; zoom: 1; *display: inline; }
哇!差不多了,只剩 IE 6 了:
IE6 不支持 min-height,但是多虧它對 height 屬性的不正確處理,我們可以用它來代替。把 _height(IE6 下劃線 hack) 設為 250px 使所有的 <li> 元素高度為 250px,並且如果它們的內容大於 250px,他們會擴大來適應。其他所有的浏覽器會忽略 _height。
現在為止,對所有的浏覽器都有效了,這是最終的 CSS 和 HTML:
<!-- li { width: 200px; min-height: 250px; border: 1px solid #000; display: -moz-inline-stack; display: inline-block; vertical-align: top; margin: 5px; zoom: 1; *display: inline; _height: 250px; } -->
<li> <div> <h4>This is awesome</h4> <img src="http://farm4.static.flickr.com/3623/3279671785_d1f2e665b6_s.jpg" alt="lobster" width="75" height="75" /></div></li>
糖伴西紅柿說:
這篇文章所講的也是非常使用的技術,其中牽涉到其他的技術,也需要大家有所了解。正好糖伴西紅柿這兩天也在看這方面的資料,提供一些資料給大家參考。
這個 bug 是“痛在遠方”同學碰到的,確實很詭異啊,貌似對標准支持越好的浏覽器才會有這個問題。
如下圖:
在 Firefox 下,inline/inline-block 的元素直接會有莫名的幾像素(貌似是6px)的空隙。這個 bug 比較難發現,因為為了美觀,一般的這種設計,inline/inline-block 的元素直接都會有一定的間距,再加上目前的浏覽器對 inline-block 這個屬性的支持並不是很好,這個屬性應用的也不是很頻繁。由跨浏覽器的inline-block來看,要對浏覽器做不少hack,代碼量以及方便性上不如直接使用浮動。因此這個 bug 的影響其實不大。
要解決這個 bug,貌似目前沒有什麼好的方法,只能改變代碼的縮進,把換行去掉,整個代碼寫入一行。