做为一个前端工程师,在编写 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…