margin系列之bug巡演

doyoe發表於2013-12-11

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

我所知道的瀏覽器margin bug

  • IE6浮動雙倍margin bug;
  • IE6浮動相鄰元素3px bug;
  • IE6/7 clear引發的margin-top bug;
  • 待補充的有一堆

為bug生為bug死為bug欲仙欲死的日子

各瀏覽器的實現差異或者由此而引入的錯誤,一直都是前端開發人員的夢魘。相信大多數的前端都為此而精疲力盡過,瀏覽器bug你所知有幾?

IE6浮動雙倍margin bug

這當是IE6最為經典的bug之一。高大上的前端,你肯定從未與其失之交臂過。

觸發方式

  • 元素被設定浮動
  • 元素在與浮動一致的方向上設定margin值

來看看詳細的程式碼吧:

HTML

<div id="demo">
    <p>IE6下浮動方向上的margin值將會雙倍於其指定值</p>
</div>

CSS

#demo p{
    float:left;
    margin-left:10px;
}

效果對比

非IE6下浮動無雙邊距 (圖一)

圖一 是非IE6下的效果

IE6下浮動雙邊距 (圖二)

圖二 是IE6下的效果

從圖一和圖二的對比,我們肉眼就可以發現區別。是的,IE6下左邊的外邊距變成了 margin-left 指定值的2倍,而其它瀏覽器下正常,這就是經典的IE6浮動元素雙倍邊距bug。來看看具體的例子:DEMO1 IE6浮動元素雙倍margin bug重現

很開心告訴你,問題要比這還更復雜一些,接著往下看。

同個浮動方向的元素只有第一個元素會double margin

double margin 並不會發生在所有的浮動元素上,同個包含塊內,在相同的浮動方向上,它只發生在第一個浮動元素上。

用程式碼說話:

HTML

<div id="demo">
    <p>第一個float:left</p>
    <p>第二個float:left</p>
    <p>第三個float:left</p>
</div>

CSS Code不變,加多2個浮動元素,再來看具體情況,有圖有真相:

同個浮動方向的元素只有第一個元素會double margin (圖三)

看到圖三結果一目瞭然,三個 float:left 的元素只有第一個元素才 double margin 了。用個例子來終結它:DEMO2 同個浮動方向的元素只有第一個元素會double margin

double margin只發生在float:left時?

你覺得呢?結果當然不會是這樣。在之前,我們只說過在同個浮動方向的第一個浮動元素會double margin,並沒有說只有 float:left 才觸發。

我們將 DEMO1 的CSS簡單改改,HTML不變

CSS

#demo p{
    float:right;
    margin-right:10px;
}

結果會是怎樣呢?看 圖四

IE6 double margin也會發生在float:right時 (圖四)

在圖四中,我們看到右側的外邊距明顯比指定值 margin-right:10px 要大,恩,確實,它是20px,也double了。瞧瞧:DEMO3 IE6 double margin也會發生在float:right時

既有左浮動又有右浮動的情況將會是怎樣呢?

我們先來將程式碼呈上:

HTML

<div id="demo">
    <p class="a">1 float:left</p>
    <p class="b">2 float:left</p>
    <p class="c">3 float:right</p>
    <p class="d">4 float:right</p>
</div>

CSS

#demo .a,#demo .b{
    float:left;
    margin-left:10px;
}
#demo .c,#demo .d{
    float:right;
    margin-right:10px;
}

是的,你可能想到了,第一個左浮動元素和第一個右浮動元素都將會出現 double margin。來看 圖五

既有左浮動又有右浮動的情況 (圖五)

左右都 double margin 了,這看似挺複雜,其實為什麼會這樣,前面都講得比較明白了,所以應該能理解?本例也奉上:DEMO4 複雜的double margin

double margin 不僅僅出現在margin-left/right

和大多數其它 margin 特性一樣,double margin 也受書寫模式 writing-mode 影響。我們在開篇所說的觸發條件之一 元素在與浮動一致的方向設定margin值 ,其實並不完全精確。當 writing-mode 為縱向時,會發生 double margin 的方向也相應變成了縱向。

當書寫模式 writing-mode 縱向時,設定 float:right 時,會發生什麼?來看程式碼:

HTML

<div id="demo">
    <p>書寫模式改變雙倍margin bug方向</p>
</div>

CSS

#demo{
    -webkit-writing-mode:vertical-rl;
    writing-mode:tb-rl;
}
#demo p{
    float:right;
    margin:10px 0;
}

CSS Code中,我們同時設定了 margin-top/bottom 的值都為 10px。你預期會 double 的方向是 top or bottom?不太確定?看到 圖六 你就知道了:

書寫模式改變IE6浮動雙倍margin bug方向 (圖六)

圖六清晰的驗證了 writing-mode 會影響 double margin 的方向;並且當設定了 float:right 時,只有 margin-bottom 會 double。看看示例吧:DEMO5 書寫模式改變IE6浮動雙倍margin bug方向

float:left 時, double margin 的將會是 top or bottom?

大家再猜猜,在書寫模式為縱向時,設定了 float:left,結果又將會如何?

我們只簡單的將 DEMO5 中的CSS改成 float:left 其餘不變,於是得到 圖七 如下:

書寫模式改變IE6浮動雙倍margin bug方向 (圖七)

你會驚訝的發現,margin-top/bottom 兩個方向都出現了 double,這真是一件好神奇的事,事實勝於雄辯:DEMO6 書寫模式縱向時margin-top/bottom都將double

寫到這,關於IE6浮動雙倍margin bug就說的差不多了,包括觸發方式,各種情景下的變化,還有解決方案。哦,解決方案貌似還沒寫...

fix IE6浮動雙倍margin bug

我們以 DEMO1 作為需要fix的case

給IE6在會 double margin 的方向上設定小一倍的margin值,如下:

CSS

#demo p{
    float:left;
    margin-left:10px;
    _margin-left:5px;
}

恩,IE6的hack,就不再贅述了。不過這種處理方式有一個明顯的缺陷,那就是不夠靈活,無法通用。因為當標準 margin 值改變時,這個值就得變化。所以不推薦使用這種方式。

display:inline

CSS

#demo p{
    _display:inline;
    float:left;
    margin-left:10px;
}

恩,仍然是only ie6的hack,不過這個方案更Cool,它不需要care margin值到底是什麼,足夠靈活。看具體的例子吧:DEMO7 修復IE6浮動雙倍margin bug。至於為什麼會有這種解法,我想只能問問微軟的童鞋了。

完全沒想到,單一個雙邊距bug就寫了這麼長的篇幅,本打算一篇文章涵蓋一堆bug,看來得分篇了。

margin系列文章:

相關文章