margin系列之bug巡演(二)

doyoe發表於2013-12-17

原文地址:margin系列之bug巡演(二) by @doyoe

IE6/7 clear引發的margin-top bug

我知道,這是一個被談及較少的bug,但我幾乎可以肯定你在遇見過的同時並沒有把它當成是一個bug。

w3c關於 clear 特性的描述

設定了 clear 為非 none 值的元素,其頂部 border 邊界在垂直方向不允許出現在之前的浮動元素底部 margin 之上。

什麼意思呢?用段程式碼來闡述:

HTML

<div class="a">float:left</div>
<div class="b">clear:left</div>

CSS

.a{
    float:left;
    height:30px;
    margin:20px;
}
.b{
    clear:left;
    height:30px;
    margin-top:-30px;
}

如上程式碼,你認為 .b 是否會相對自身向上偏移 30px 呢?然後蓋住 .a 底部 10px?如果你真這麼猜想,那就錯了。

來看上述程式碼,我們會得到什麼樣的結果,如 圖一

clear margin(圖一)

恩,你覺得這可能會是落後瀏覽器才這樣,比如IE6/7。很高興的告訴你,其實高階瀏覽器才這樣,IE6/7的表現會是之前你猜想的那樣,如下 圖二

clear margin(圖二)

不論你相信與否,看個例子你就明白了 DEMO1clear margin 猜想,你會發現就算將 margin-top 去掉,.b 的位置也絲毫不會改變。

為什麼會這樣?

我們已經說過設定了 clear 為非 none 值的元素其頂部 border 邊界不允許出現在之前浮動元素的底部margin邊界之上。也就是說必須在垂直方向上遞次堆疊卻不能重合。

所以說高階瀏覽器是遵循w3c規範的,而IE6/7的實現明顯有悖該規則。

雖然擁有 clear 特性的元素其 border 頂部邊界不允許超越之前浮動元素的底部margin邊界之上,但是其margin可以和之前浮動元素的任何區域重合。我們稍微改下之前程式碼:

HTML

<div class="a">float:left</div>
<div class="b">clear:left</div>

CSS

.a{
    float:left;
    height:30px;
    margin:20px;
}
.b{
    clear:left;
    height:30px;
    margin-top:50px;
}

我們將 .bmargin-top 修改為一個正值,能得到如下 圖三

clear margin(圖三)

圖中的黃色區域是 .bmargin-top,你會發現,它可以和 .a 的任何區域重合。同時,你也可以發現 圖三圖一 居然是一樣的效果,.b 的實際位置都沒變化過。來看例子 DEMO2clear margin 驗證

這是否說明擁有 clear 特性的元素對其之前的浮動元素沒有任何影響?因為不論是正值還是負值,其位置都不會發生變化。

如果你這樣想,那你就又錯了。

擁有clear特性的元素其margin緊鄰之前的浮動元素依然有效

是的,在某個臨界值,這一切會發生改變,並非全然無效。

這個臨界值是什麼?

臨界值是包含塊內浮動元素的實際高度,即浮動元素的 margin + border + padding + height,拿我們的 DEMO2 來詳述:

DEMO2 中的浮動元素 .a 的實際高度為 30 + 20*2 = 70px,也就說當 .bmargin-top 大於 70px 時,超過的部分將會使得 .b 發生偏移。

CSS

.b{
    clear:left;
    height:30px;
    margin-top:100px;
}

我們將 DEMO2 中的 margin-top 改成 100px,再看看具體情況 DEMO3clear margin 驗證2,你可以手動的修改其 margin-top 值,看看臨界值是否如前所述。

解決方案

IE6/7下由 clear 特性引發的 margin-top bug,並沒有像 double margin 那樣的萬精油 display:inline 解決方案,所以需要尋求的是讓IE6/7和其它瀏覽器繞過此問題來進行解決。

例如:

  • 儘量避免為設定了 clear 為非 none 值的元素定義margin-top;
  • 如果必須,可以將擁有 clear 特性的元素作為容器,在其子元素上設定margin-top;
  • 視情況換成padding-top;

要注意的問題

.a.b 需要在處在同一個塊級上下文內,或者其包含塊擁有 padding-top/border-top,否則臨界值情況將失效,不過任何IE目前都不需要此前置條件。用IE和非IE檢視 DEMO4clear margin 驗證3

margin系列文章:

相關文章