做爲一個前端工程師,在編寫 CSS 時外邊距摺疊及 BFC 都是常常遇到的狀況,今天就來作一下總結。css
在 CSS 中,兩個或者多個普通流中相鄰盒子的邊距在垂直方向上會發生摺疊的這種現象叫作外邊距摺疊。外邊距摺疊分爲父子外邊距摺疊及兄弟外邊距摺疊。html
咱們給 child
添加了 margin-top
,卻致使 body
總體下移。前端
咱們給 child1
設置了 margin-bottom:20px
,給 child2
設置了 margin-top: 50px
,但最終的展示效果確實 50px
(注意:若是 margin 設置負值的話是什麼狀況的?能夠思考一下😯)css3
那麼觸發外邊距摺疊的條件是什麼呢?W3C文檔裏已做出了說明,須要符合下面條件:git
注意這裏的「相鄰元素」多是兄弟節點也多是父子節點,好比:一個元素的 margin-top
和它的第一個普通流子元素的 margin-top
;一個元素的 margin-bottom
和它下一個普通流兄弟的 margin-top
;一個高度爲 auto 元素的 margin-bottom
和它的最後一個子元素的 margin-bottom
github
前面已經提到了觸發外邊距摺疊的條件,若是要避免外邊距摺疊只需破壞掉觸發的條件便可,好比建立一個 BFC。前端工程師
對於建立 BFC 的詳細方法,引用知乎用戶的回答就是:ide
根據 BFC 的定義,兩個元素只有在同一 BFC 內,纔有可能發生垂直外邊距的重疊,包括相鄰元素、嵌套元素。要解決 margin 重疊問題,只要讓它們不在同一個 BFC 內就行。對於相鄰元素,只要給它們加上 BFC 的外殼,就能使它們的 margin 不重疊;對於嵌套元素,只要讓父級元素觸發 BFC,就能使父級 margin 和當前元素的 margin 不重疊。佈局
固然也要規範寫法,好比設置 margin 時,儘可能使各個元素 margin 方向保持一致,這樣也能提升 CSS 代碼的可讀性。flex
那麼什麼是 BFC 呢?以及如何建立一個 BFC 呢?接下來就來詳細看一下。
BFC(Block Formatting Context)即塊級格式化上下文,W3C 規範對此做了詳細的描述,翻譯過來大概以下:
浮動元素和絕對定位元素,非塊級盒子的塊級容器(例如 inline-blocks
, table-cells
, 和 table-captions
),以及 overflow
值不爲visiable
的塊級盒子,都會爲他們的內容建立新的 BFC(塊級格式上下文)。
在 BFC 中,盒子從頂端開始垂直的一個接一個排列,兩個盒子之間的垂直間距由他們的 margin
值決定,在同一個 BFC 中,兩個相鄰塊級盒子的垂直外邊距會產生摺疊。
在 BFC 中,每個盒子的左外邊緣會觸碰到容器的左邊緣,對於從右到左的格式來講,則觸碰到右邊緣。即便在浮動裏也是這樣的(儘管一個盒子的 line boxes
會由於浮動而收縮),除非這個盒子的內部建立了一個新的 BFC(因爲浮動,在這種狀況下盒子自己 將會變得更窄
Line Box: www.w3.org/TR/2002/WD-…
經過上面的描述,建立一個 BFC 只需知足如下條件之一便可:
float
的值不爲 none
overflow
的值不爲 visible
position
的值不爲 static
或者 relative
display
的值爲 table-cell
, table-caption
, inline-block
, flex
或 inline-flex
其中之一例如在本文開篇的第一個父子元素邊距摺疊的問題,咱們只需在父元素上增長 overflow: hidden
觸發 BFC 便可:
邊距摺疊的問題能夠用 BFC 來解決,但觸發 BFC 並非解決邊距摺疊的充分條件,還要獲得合理的運用,下面就是使用 BFC 來解決的一些問題。
對於兄弟元素,只要給它們加上 BFC 的外殼,對它們進行隔離,就能使它們的 margin
不折疊,例如:
<div class="parent">
<div class="bfc">
<div class="child child1">child1</div>
</div>
<!-- 本示例中只對其中一個加 bfc 外殼也能夠,保證不在同一個 bfc 中-->
<div class="bfc">
<div class="child child2">child1</div>
</div>
</div>
複製代碼
對於父子元素,只要讓父級元素觸發 BFC,就能使父級的 margin
和當前元素的 margin
不折疊。
例如咱們在一個容器中,對其子元素進行了浮動處理,那麼因爲子元素脫離文檔流,容器的高度會發生塌陷,這個時候就能夠經過觸發容器的 BFC 來解決。
能夠對示例中的 parent
添加 overflow: hidden
來觸發 BFC,從而使容器高度恢復:
固然,對於相似問題咱們經常會經過 clearfix
清除浮動來解決,以保證普適性,不過 BFC 也不失爲一種不錯的解決辦法。
好比以下示例,咱們但願 child2
位於 child1
的右方,可是此時 child1
與 child2
的一部分卻重合了,這並非咱們想要的效果。
這是因爲在 BFC 中,每個盒子的左外邊緣會觸碰到容器的左邊緣,對於從右到左的格式來講,則觸碰到右邊緣,即便在浮動裏也是這樣的(儘管一個盒子的 line boxes
會由於浮動而收縮)。而這裏 p
元素的文本部分就進行了收縮,爲浮動元素提供空間。
那麼此時爲了解決這個問題,只需觸發 p
元素的 BFC 便可,好比爲 p
元素添加一個 overflow: hidden
:
float
的值不爲 none
overflow
的值不爲 visible
position
的值不爲 static
或者 relative
display
的值爲 table-cell
, table-caption
, inline-block
, flex
或 inline-flex
其中之一本文代碼示例地址:github.com/taroalan/bl…