【深刻BFC】 關於CSS中float佈局,清除浮動,和margin合併的原理解析,解開你心中的那些困惑!

BFC的通俗理解:

  Block Formatting Context(塊級格式化上下文)是W3C CSS 2.1 規範中的一個概念,它決定了元素如何對其內容進行定位,以及與其餘元素的關係和相互做用。瀏覽器

  簡單來說,咱們能夠把它理解爲,咱們在進行盒模型佈局的時候,若是一個元素符合了成爲BFC的條件,該元素成爲一個隔離了的獨立容器,元素內部元素會垂直的沿着其父元素的邊框排列,和外部元素互不影響 。好比浮動元素會觸發BFC,浮動元素內部的子元素主要受到該浮動元素的影響,而兩個浮動元素之間是互不影響的。佈局

  在CSS3 中,BFC 叫作Flow Root。在早期的ie中也有相似的概念haslayout IE六、7的不少佈局產生的bug(如3px間隙、絕對定位的繼承寬度)均可以經過觸發hasLayout修復,比較推薦的方法爲zoom:1與height:1%,不會破壞已有的樣式,相信你們對它並不陌生。spa

  一樣的以往集中在float、絕對定位、margin collaspe中的不少困惑,在理解了bfc後,都可以被咱們一一解除 。.net


BFC規範中的定義:

w3c規範對BFC的解釋:
  浮動元素和絕對定位元素,不是塊級盒子的塊容器 (如 inline-blocks, table-cells, 和 table-captions),以及設置了overflow屬性(除了visible)的塊級盒子 ,都會爲他們的內容建立新的BFC(塊級格式上下文)。
  在BFC中,盒子從頂端開始垂直地 一個接一個地排列,兩個盒子之間的垂直的間隙是由他們的margin 值所決定的。在一個BFC中,兩個相鄰的塊級盒子的垂直外邊距會產生摺疊。
  在BFC中,每個盒子的左外邊緣(margin-left)會觸碰到容器的左邊緣(border-left)(對於從右到左的格式來講,則觸碰到右邊緣)。code

觸發BFC的方法:

float 元素
position(absolute,fixed)
display (table-cell,table-caption,inline-block)
overflow 除了visible 之外的值(hidden,auto,scroll )
fieldset元素
早期IE的hasLayout會觸發一個新的block formatting contextorm

BFC的特性cdn

  1. 邊緣不和浮動元素重疊
  2. 不存在collapsing margins問題

  第一個特性特別有用,由於元素觸發了BFC的話,就不會被float元素覆蓋,當子元素所有浮動的時候也可以正確地包含了
  第二個margin不會疊加的特性,能夠理解爲兩個處於普通流的盒子,會有margin疊加的問題,是由於他們屬於相同的BFC,當他自身建立了一個新的BFC時,這個問題就不存在了blog

BFC的常見應用

1.經過邊緣不和浮動元素重疊的特性,實現兩欄結構。繼承

  若是一個浮動元素後面跟着一個非浮動的元素,那麼就會產生一個覆蓋的現象,經過觸發BFC來清除覆蓋,不少自適應的兩欄佈局就是這麼作的。
下面咱們來看左邊圖片+右邊信息的示例:圖片

// CSS
div,p{margin:0;padding:0;}
.box {width:320px;}
.img {width: 80px;height: 80px;margin-right:10px;float:left;}
.info {background: #ff9;color: #404040;}

// HTML
<div class="box">
    <div class="img"><img src="http://wwc.taobaocdn.com/avatar/getAvatar.do?userNick=feihu2987&width=80&height=80&type=sns" width="80" height="80" alt="頭像"></div>
    <p class="info">風吹亮雪花,吹白咱們的頭髮,當初說一塊兒闖天下,大家還記得嗎?</p>
</div>

通常狀況下它呈現出咱們所樂意看到的樣子:

但隨着文字信息增多後,會變地很是的糟糕:

很明顯,這是由於info類裏面的文字受到了浮動元素的影響,但這並非咱們所指望的。此時咱們能夠爲P元素的內容創建一個BFC,讓其內容消除對外界浮動元素的影響。根據上文所知,只要給info元素添加overflow:hidden;便可爲其內容創建新的BFC。固然你也能夠經過其餘方法來創建。其效果以下:

至此,咱們能夠拋棄計算設置左邊邊距,或是設置右邊浮動再清除父元素的浮動這些弱爆的方式了。

demo地址: http://jsfiddle.net/k9u5x/

固然考慮到ie6 7 的兼容性,咱們同時觸發一下 haslayout就再好不過了,更多示例請看豆瓣小組和閱讀中,不少地方使用了此方式:

http://www.douban.com/group/explore/culture

.channel-item .bd, .channel-item .block,.channel-item .block p, .mod .hd, .channel-group-rec li, .channel-group-rec li .info {
    overflow: hidden;
    zoom: 1;
}


2.清除元素內部浮動

只要把父元素設爲BFC就能夠清理子元素的浮動了,一樣的由於IE6-7不支持BFC,所以要設置zoom:1來觸發hasLayout 閉合浮動。

咱們最多見的兼容用法就是在父元素上添加class clearfix ;

.clearfix {*zoom:1}
.clearfix:after{content:"\0020";display:block;height:0;clear:both;visibility:hidden}

 

3.解決合併外邊距的問題

  在CSS當中,相鄰的兩個盒子(多是兄弟關係也多是父子關係)的外邊距能夠結合成一個單獨的外邊距。這種合併外邊距的方式被稱爲摺疊,而且於是所結合成的外邊距稱爲摺疊外邊距。
  按照BFC的定義,只有同屬於一個BFC時,兩個元素纔有可能發生垂直Margin的重疊,這個包括相鄰元素,嵌套元素,只要他們之間沒有線盒(其實就是非空內容),沒有間隙(clearance,設置clear以閉合相關方向的浮動 ),沒有padding和border將他們分隔開就會發生margin重疊。

  所以要解決margin重疊問題,只要讓它們不在同一個BFC就好了,可是對於兩個相鄰元素來講,意義不大,沒有必要給它們加個外殼,可是對於嵌套元素來講就頗有必要了,只要把父元素設爲BFC就能夠了。這樣子元素的margin就不會和父元素的margin發生摺疊了。

摺疊的結果:

兩個相鄰的外邊距都是正數時,摺疊結果是它們二者之間較大的值( 10px 20px 結果爲20px )。
兩個相鄰的外邊距都是負數時,摺疊結果是二者絕對值較大的值( -10px -20px 結果是-20px )。
兩個外邊距一正一負時,摺疊結果是二者的相加的和( 10px -20px 結果是10px )。
產生摺疊的必備條件:margin必須是邊緣毗鄰的

而根據w3c規範,兩個margin是垂直毗鄰的必須知足如下條件:

元素的margin-top與其第一個常規文檔流的子元素的margin-top
元素的margin-bottom與其下一個常規文檔流的兄弟元素的margin-top
height爲auto的元素的margin-bottom與其最後一個常規文檔流的子元素的margin-bottom
高度爲0而且最小高度也爲0,不包含常規文檔流的子元素,而且自身沒有創建新的BFC的元素的margin-top和margin-bottom
只要觸發Block Formatting Contexts的條件 或者是使用非空內容,空隙(clearance),padding和border將他們分隔開margin便不會摺疊。

分析一:浮動和絕對定位不與任何元素產生 margin 摺疊

緣由:浮動元素和絕對定位元素不與其餘盒子產生外邊距摺疊是由於元素會脫離當前的文檔流,違反了上面所述的兩個margin是鄰接的條件同時,又由於浮動和絕對定位會使元素爲它的內容建立新的BFC,所以該元素和子元素所處的BFC是不相同的,所以也不會產生margin的摺疊。

分析二:inline-block元素與其兄弟元素、子元素和父元素的外邊距都不會摺疊(包括其父元素和子元素)

inline-block不符合w3c規範所說元素必須是塊級盒子的條件,由於規範中又說明,塊級盒子的display屬性必須是如下三種之一:'block', 'list-item', 和 'table'。

分析三:設置有些屬性(如float、position、display)會同時造成BFC與觸發hasLayout,或者在>=IE7時也能夠設置overflow同時搞定二者。

在IE7如下,只觸發(造成)了其中一個,也最好同時觸發(造成)另外一個,以保證瀏覽器的兼容。
簡單的觸發方法:{overflow: hidden;zoom:1;}

 

若是感受閱讀此文後,有必定的啓發和收穫,勞駕您推薦下,在此謝過,歡迎留言交流。

相關文章
相關標籤/搜索