BFC究竟是什么?为啥能解决外边距坍塌问题?
问题描述
在做项目的过程中,我发现了浏览器渲染的一个特殊的点:外边距坍塌!
只有普通文档流中块框的垂直外边距才会发生外边距合并。行内框、浮动框或绝对定位之间的外边距不会合并。
哭泣!!
在父子块状元素的如上图下面部分的样式,如果我们不想让浏览器执行这个默认操作,有如下的解决方法:
- 父元素是BFC元素
- 父元素拥有border
- 父元素拥有padding
- 子元素是可置换元素或display为inline-block、inline-table、table-caption的元素
BFC? 这是什么? 让我们细细道来。
在 普通流 中的盒子会参与一种格式上下文,这个盒子可能是块盒也可能是行内盒,但不可能同时是块盒又是行内盒。块级盒参与块级格式上下文( BFC ),行内级盒参与行级格式上下文( IFC )。BFC内部元素和外部元素不会互相影响。
除了BFC和IFC,我们的flex布局参加 FFC( flex formatting context ) , grid布局参加 GFC(grid formatting context)
BFC
BFC(Block Formatting Context,属于普通流) ,独立渲染区域,区域内 垂直方向上 相邻的块级元素会发生margin合并
触发BFC特性
- body 根元素
- 浮动元素:float 除 none 以外的值
- position的值不为 static 或 relative (absolute、fixed)
- display 为 inline-block、table-cells、flex、grid
- overflow 除了 visible 以外的值 (hidden、auto、scroll)
BFC的特性
- 子元素的CSS样式不会影响BFC元素外部
1 | //bfc |
说明:
普通块级元素,其子元素的margin-top,不会隔开自身与父元素(普通块级元素),但是会作用到父元素外部(将父元素和叔伯元素或祖父元素隔开);
BFC元素,作为一个独立、封闭的渲染区域,其子元素的margin-top,则会隔开自身与父元素(BFC元素),而不会影响到父元素外部;
- 浮动子元素参与BFC父元素的高度计算,也就是BFC元素能够识别浮动元素(将元素声明为BFC元素,也是clearfix解决父元素塌陷问题的一种常用方法)
1
2
3
4
5
6
7<div style="background-color: #F6B7B7">
<div style="margin: 20px;float: left;">我是块级元素,margin为20</div>
</div>
<div style="margin: 20px;overflow: hidden;background-color: #F6B7B7">
<div style="margin: 20px;float: left;">我是块级元素,margin为20</div>
</div>
- 占据文档流的BFC元素(可使用overflow: auto创建),能够识别浮动的兄弟元素;
1
2
3
4
5
6
7
8
9<div style="margin: 20px;background-color: #F6B7B7">
<div style="margin: 20px;float: left;background-color: #890909">我是浮动元素</div>
<div style="margin: 20px;background-color: #FFE0E0">我是普通元素呀呀呀呀呀呀呀呀</div>
</div>
<div style="margin: 20px;background-color: #F6B7B7">
<div style="margin: 20px;float: left;background-color: #890909">我是浮动元素</div>
<div style="margin: 20px;overflow: hidden;background-color: #FFE0E0">我是BFC块呀呀呀呀呀呀呀呀呀</div>
</div>
- 占据文档流的BFC元素(可使用overflow: auto创建),width为auto时,会占满当前行的剩余宽度,但margin-left设置没有用; 如上图,BFC元素设置了margin-left,但是没有作用。
总结
BFC会阻止垂直外边距(margin-top、margin-bottom)折叠
BFC不会重叠浮动元素
BFC高度可以包含浮动
那么,IFC又是什么?
IFC
在IFC中,盒子水平放置,一个接着一个,从包含块的顶部开始。水平margins,borders,和padding在这些盒子中被平分。这些盒子也许通过不同的方式进行对齐:他们的底部和顶部也许被对齐,或者通过文字的基线进行对齐。矩形区域包含着来自一行的盒子叫做line box。line box 的宽度由浮动情况和它的包含块决定。line box的高度由 line-height 的计算结果决定。
具体介绍可见下一篇~《页面布局的简单介绍》