# margin系列之bug巡演(二)
>原作者:doyoe
原文鏈接:http://blog.doyoe.com/2013/12/17/css/margin%E7%B3%BB%E5%88%97%E4%B9%8Bbug%E5%B7%A1%E6%BC%94%EF%BC%88%E4%BA%8C%EF%BC%89/
## IE6/7 clear引發的margin-top bug
我知道,這是一個被談及較少的bug,但我幾乎可以肯定你在遇見過的同時并沒有把它當成是一個bug。
## w3c關于 clear 特性的描述
設置了 `clear` 為非 `none` 值的元素,其頂部 `border` 邊界在垂直方向不允許出現在之前的浮動元素底部 `margin` 之上。
什么意思呢?用段代碼來闡述:
### HTML
```html
<div class="a">float:left</div>
<div class="b">clear:left</div>
```
### CSS
```css
.a{
float:left;
height:30px;
margin:20px;
}
.b{
clear:left;
height:30px;
margin-top:-30px;
}
```
如上代碼,你認為 `.b` 是否會相對自身向上偏移 `30px` 呢?然后蓋住 `.a` 底部 10px?如果你真這么猜想,那就錯了。
來看上述代碼,我們會得到什么樣的結果,如 `圖一`:
(圖一)
恩,你覺得這可能會是落后瀏覽器才這樣,比如IE6/7。很高興的告訴你,其實高級瀏覽器才這樣,IE6/7的表現會是之前你猜想的那樣,如下 `圖二`:
(圖二)
不論你相信與否,看個例子你就明白了 `DEMO1`:[clear margin 猜想](http://demo.doyoe.com/css/margin/bug/clear-margin.html),你會發現就算將 `margin-top` 去掉,`.b` 的位置也絲毫不會改變。
## 為什么會這樣?
我們已經說過設置了 `clear` 為非 `none` 值的元素其頂部 `border` 邊界不允許出現在之前浮動元素的底部margin邊界之上。也就是說必須在垂直方向上遞次堆疊卻不能重合。
所以說高級瀏覽器是遵循w3c規范的,而IE6/7的實現明顯有悖該規則。
``
雖然擁有 `clear` 特性的元素其 `border`
頂部邊界不允許超越之前浮動元素的底部margin邊界之上,但是其margin可以和之前浮動元素的任何區域重合。我們稍微改下之前代碼:
### HTML
```html
<div class="a">float:left</div>
<div class="b">clear:left</div>
```
### CSS
```css
.a{
float:left;
height:30px;
margin:20px;
}
.b{
clear:left;
height:30px;
margin-top:50px;
}
```
我們將 `.b` 的 `margin-top` 修改為一個正值,能得到如下 `圖三`:
(圖三)
圖中的黃色區域是 `.b` 的 `margin-top`,你會發現,它可以和 `.a` 的任何區域重合。同時,你也可以發現 `圖三` 和 `圖一` 居然是一樣的效果,`.b` 的實際位置都沒變化過。來看例子 `DEMO2`:[clear margin 驗證](http://demo.doyoe.com/css/margin/bug/clear-margin-2.html)
這是否說明擁有 `clear` 特性的元素對其之前的浮動元素沒有任何影響?因為不論是正值還是負值,其位置都不會發生變化。
如果你這樣想,那你就又錯了。
## 擁有clear特性的元素其margin緊鄰之前的浮動元素依然有效
是的,在某個臨界值,這一切會發生改變,并非全然無效。
這個臨界值是什么?
臨界值是包含塊內浮動元素的實際高度,即浮動元素的 margin + border + padding + height,拿我們的 `DEMO2` 來詳述:
`DEMO2` 中的浮動元素 .a 的實際高度為 30 + 20*2 = 70px,也就說當 `.b` 的 `margin-top` 大于 `70px` 時,超過的部分將會使得 .b 發生偏移。
### CSS
```ccss
.b{
clear:left;
height:30px;
margin-top:100px;
}
```
我們將 `DEMO2` 中的 `margin-top` 改成 100px,再看看具體情況 `DEMO3`:[clear margin 驗證2](http://demo.doyoe.com/css/margin/bug/clear-margin-3.html),你可以手動的修改其 `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查看 `DEMO4`:[clear margin 驗證3](http://demo.doyoe.com/css/margin/bug/clear-margin-4.html)