由於BFC的理解對咱們徹底地弄懂margin collapse是不可缺乏的。因此讓咱們先來認識一下BFC。html
首先咱們來看看w3c規範對BFC的解釋,其實對於這種概念的學習上,咱們老是建議首先尋找官方的定義,由於原則上來講官方的纔是最權威和正確的,並且還比較詳細,千萬不要由於看到英文就畏懼不前。app
浮動元素和絕對定位元素,非塊級盒子的塊級容器(例如 inline-blocks, table-cells, 和 table-captions),以及overflow值不爲「visiable」的塊級盒子,都會爲他們的內容建立新的BFC(塊級格式上下文)。佈局
在BFC中,盒子從頂端開始垂直地一個接一個地排列,兩個盒子之間的垂直的間隙是由他們的margin 值所決定的。在一個BFC中,兩個相鄰的塊級盒子的垂直外邊距會產生摺疊。學習
在BFC中,每個盒子的左外邊緣(margin-left)會觸碰到容器的左邊緣(border-left)(對於從右到左的格式來講,則觸碰到右邊緣)。網站
首先BFC是一個名詞,是一個獨立的佈局環境,咱們能夠理解爲一個箱子(其實是看不見摸不着的),箱子裏面物品的擺放是不受外界的影響的。轉換爲BFC的理解則是:BFC中的元素的佈局是不受外界的影響(咱們每每利用這個特性來消除浮動元素對其非浮動的兄弟元素和其子元素帶來的影響。)而且在一個BFC中,塊盒與行盒(行盒由一行中全部的內聯元素所組成)都會垂直的沿着其父元素的邊框排列。spa
在w3c的規範中,除了上面的一段定義以外,BFC的相關知識點分佈地比較零散,但基本集中在float、絕對定位、margin collaspe中。下面咱們來看看如何應用到BFC來解決問題。code
在不少網站中,咱們常常會看到這樣的一種,左邊圖片+右邊信息的兩欄結構,下面咱們來看看如何利用BFC來實現。orm
首先咱們給出這樣的結構:htm
1 .box {width:210px;border: 1px solid #000;float: left;} 2 .img {width: 100px;height: 100px;background: #696;float: left;} 3 .info {background: #ccc;color: #fff;}
1 <div class="box"> 2 <div class="img">image</div> 3 <p class="info">信息信息信息信息信息信息信息信息信息信息信息信</p> 4 </div>
通常狀況下它呈現出咱們所樂意看到的樣子:blog
但隨着文字信息增多後,會變地很是的糟糕:
很明顯,這是由於info類裏面的文字受到了浮動元素的影響,但這並非咱們所指望的。此時咱們能夠爲P元素的內容創建一個BFC,讓其內容消除對外界浮動元素的影響。根據上文所知,只要給info元素添加overflow:hidden;便可爲其內容創建新的BFC。固然你也能夠經過其餘方法來創建。其效果以下:
在CSS當中,相鄰的兩個盒子(多是兄弟關係也多是祖先關係)的外邊距能夠結合成一個單獨的外邊距。這種合併外邊距的方式被稱爲摺疊,而且於是所結合成的外邊距稱爲摺疊外邊距。
而根據w3c規範,兩個margin是鄰接的必須知足如下條件:
(下面咱們對不產生摺疊的狀況逐一分析。)
緣由:浮動元素和絕對定位元素不與其餘盒子產生外邊距摺疊是由於元素會脫離當前的文檔流,違反了上面所述的兩個margin是鄰接的條件同時,又由於浮動和絕對定位會使元素爲它的內容建立新的BFC,所以該元素和子元素所處的BFC是不相同的,所以也不會產生margin的摺疊。
DEMO:
1 * {padding:0;margin: 0; text-align: center;} 2 .wrapper {margin:30px;width: 450px;border:1px solid red;} 3 .small-box {width: 50px;height: 50px;margin: 10px;background: #9cc;} 4 .middle-box {width: 100px;height: 100px;margin: 20px;background: #99c;} 5 .big-box {width: 120px;height: 120px;margin: 20px;background: #33e;} 6 .floatL {float: left;} 7 .floatR {float: right;} 8 .clear {clear: both;} 9 .posA {position: absolute;} 10 .overHid{overflow: hidden;} 11 .red {background: #f00;} 12 .green {background: #0f0;} 13 .blue {background: #00f;}
1 <div class="wrapper overHid"> 2 <div class="big-box blue">non-float</div> 3 <div class="middle-box green floatL"> 4 <div class="small-box red"></div> 5 float left 6 </div> 7 </div>
可是浮動元素脫離了當前的BFC並不影響它後面的兄弟元素,後面的兄弟元素與浮動元素前面的元素依然在同一個BFC當中,因此,它們之間的margin仍是會摺疊的。下面咱們對上面的demo作一下修改:
1 <div class="wrapper overHid"> 2 <div class="big-box">non-float</div> 3 <div class="middle-box green floatL">float left</div> 4 <div class="middle-box red">non-clear</div> 5 </div>
從上面這個修改後的demo中能夠看出,紅色的塊盒在沒有清楚浮動的狀況下,它的margin-top和藍色塊盒的margin-bottom產生了摺疊,這證實了我上面的結論。
下面咱們來談談 'clearance' 這個神奇的東西,當浮動元素以後的元素設置clear以閉合相關方向的浮動時,根據w3c規範規定,閉合浮動的元素會在其margin-top以上產生必定的空隙(clearance,以下圖),該空隙會阻止元素margin-top的摺疊,並做爲間距存在於元素的margin-top的上方。關於這個間距的計算稍微有點複雜,但實際工做中你並不須要去計算它,咱們先來看看例子吧:
1 <div class="wrapper overHid"> 2 <div class="big-box" style="box-shadow:0 20px 0 rgba(0,0,255,0.2);">non-float</div> 3 <div class="middle-box green floatL" style="opacity:0.6">float left</div> 4 <div class="middle-box red clear" style="margin-top:40px;box-shadow:0 -40px 0 rgba(255,0,0,0.2);">clear</div> 5 </div>
上面的圖中咱們能夠看到,咱們爲紅色塊盒設置的40px的margin-top(這裏咱們經過相同高度的陰影來將其可視化)好像並無對紫色塊盒起做用,並且不管咱們怎麼修改這個margin-top值都不會影響紅色塊盒的位置,而只由綠色塊盒的margin-bottom所決定。
也就是說,咱們只須要知道,閉合浮動的元素的border-top會緊貼着相應的浮動元素的margin-bottom。
原來,經過w3c的官方規範可知,閉合浮動的塊盒在margin-top上所產生的間距(clearance)的值與該塊盒的margin-top之和應該足夠讓該塊盒垂直的跨越浮動元素的margin-bottom,使閉合浮動的塊盒的border-top剛好與浮動元素的塊盒的margin-bottom相鄰接。
用上圖例子中的相關值能夠得出這樣一個式子:r-margin-top + r-clearance = g-margin-top + g-height + g-margin-bottom
PS!閉合浮動並不能使浮動元素回到原來的BFC當中!
inline-block不符合w3c規範所說元素必須是塊級盒子的條件,由於規範中又說明,塊級盒子的display屬性必須是如下三種之一:'block', 'list-item', 和 'table'。
參考資料