众所周知,CSS中的一些知识点都非常琐碎的,这其中关于BFC的部分又是非常基础且非常重要的,下面对BFC从实用角度展开介绍。
什么BFC
Formatting Context:指页面中的一个渲染区域,并且拥有一套渲染规则,他决定了其子元素如何定位,以及与其他元素的相互关系和作用。
BFC:块级格式化上下文,通过CSS属性构造的独立渲染区域,只有Block-level Box参与,该区域拥有一套渲染规则来约束块级盒子的布局,且与区域外部无关。
产生条件
CSS2.1中规定满足下列CSS声明之一的元素便会生成BFC:
- 根元素
- float的值不为none
- overflow的值不为visible
- display的值为inline-block、table-cell、table-caption
- position的值为absolute或fixed
另: display:table也认为可以生成BFC,在于table会默认生成一个匿名的table-cell。
约束规则
浏览器对于BFC这块区域的约束规则如下:
- 生成BFC元素的子元素会一个接一个的放置。垂直方向上他们的起点是一个包含块的顶部,两个相邻子元素之间的垂直距离取决于元素的margin特性。在BFC中相邻的块级元素外边距会折叠。
- 生成BFC元素的子元素中,每一个子元素做外边距与包含块的左边界相接触,(对于从右到左的格式化,右外边距接触右边界),即使浮动元素也是如此(尽管子元素的内容区域会由于浮动而压缩),除非这个子元素也创建了一个新的BFC(如它自身也是一个浮动元素)。
因此我也可以这么说
- 内部的Box会在垂直方向上一个接一个的放置。
- 垂直方向上的距离由margin决定。(完整的说法是:属于同一个BFC的两个相邻Box的margin会发生重叠,与方向无关。)
- 每个元素的左外边距与包含块的左边界相接触(从左向右),即使浮动元素也是如此。(这说明BFC中子元素不会超出他的包含块,而position为absolute的元素可以超出他的包含块边界)
- BFC的区域不会与float的元素区域重叠。
- 计算BFC的高度时,浮动子元素也参与计算,即:可以撑开容器。
- BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面元素,反之亦然。
什么是Margin Collapse
Margin塌陷、合并、折叠。
即两个相邻盒子的Margin发生合并,两个盒子可能是父子、同辈关系。
产生条件
根据w3c规范,两个margin是邻接的必须满足以下条件:
- 必须是处于常规文档流(非float和绝对定位)的块级盒子,并且处于同一个BFC当中。
- 没有线盒,没有空隙(clearance,下面引用的资料里有详细说明。),没有padding和border将他们分隔开。
- 都属于垂直方向上相邻的外边距,可以是下面任意一种情况:
- 元素的margin-top与其第一个常规文档流的子元素的margin-top
- 元素的margin-bottom与其下一个常规文档流的兄弟元素的margin-top
- height为auto的元素的margin-bottom与其最后一个常规文档流的子元素的margin-bottom
- 高度为0并且最小高度也为0,不包含常规文档流的子元素,并且自身没有建立新的BFC的元素的margin-top和margin-bottom
形成分析
总体上说是两点,BFC和clearance( 间隙 )。
- 创建了新的BFC的元素(例如浮动元素或者’overflow’值为’visible’以外的元素)与它的子元素的外边距不会折叠。
- 浮动元素不与任何元素的外边距产生折叠(包括其父元素和子元素)。
- 绝对定位元素不与任何元素的外边距产生折叠。
- inline-block元素不与任何元素的外边距产生折叠。
- 一个常规文档流元素的margin-bottom与它下一个常规文档流的兄弟元素的margin-top会产生折叠,除非它们之间存在间隙(clearance)。
- 一个常规文档流元素的margin-top 与其第一个常规文档流的子元素的margin-top产生折叠,条件为父元素不包含 padding 和 border ,子元素不包含 clearance。
- 一个 ‘height’ 为 ‘auto’ 并且 ‘min-height’ 为 ‘0’的常规文档流元素的 margin-bottom 会与其最后一个常规文档流子元素的 margin-bottom 折叠,条件为父元素不包含 padding 和 border ,子元素的 margin-bottom 不与包含 clearance 的 margin-top 折叠。
- 一个不包含border-top、border-bottom、padding-top、padding-bottom的常规文档流元素,并且其 ‘height’ 为 0 或 ‘auto’, ‘min-height’ 为 ‘0’,其里面也不包含行盒(line box),其自身的 margin-top 和 margin-bottom 会折叠。
合并结果:
- 两个相邻的外边距都是正数时,折叠结果是它们两者之间较大的值。
- 两个相邻的外边距都是负数时,折叠结果是两者绝对值的较大值。
- 两个外边距一正一负时,折叠结果是两者的相加的和。
解决Margin Collapse
总结
显然,根据BFC相关知识可以解释很多CSS的知识点,如
- overflow、absolute、float可以用来清除浮动
因此深入了解BFC对HTML+CSS基础非常重要,可以这么说,绝大多数的CSS书写都是按照BFC规则来的,因此构造BFC也是多数情况下CSS书写的 最彻底方案 ,从我个人的经验来说,很多怪异的样式问题尝试构造BFC都能解决,当然学习本身就是一个不停实践不停试错的过程,以下是利用BFC解决的常见问题,不做深入解读。
- 解决Margin Collapse (Margin合并的元素其一BFC就可解决,不仅限于用这个来解决)
- 清除浮动
- 多栏布局
参考资料:
深入理解BFC和Margin Collapse尤其是此文有对 clearance 小间隙的细致说明
我对BFC的理解