爱客仕-前端团队博客园

css中的BFC

前言

说起BFC,一些不熟悉的童鞋往往会有两种情况:

  1. 无形中用了BFC,但是不知道有这回事
  2. 请教过大佬,听过BFC大名,然后CV了一段overflow: hidden解决了问题。然后不刨根问底,笔者曾经也是其中的一员。思维不清晰肿么办?问谷歌娘呗~看了好多文章,知道自己没有过目不忘的本事,还是觉得要自己动手写写,一来加深印象,二来方便日后追溯,故撰此文。

什么是BFC?

w3c是这么解释的:

​ 浮动元素和绝对定位元素,非块级盒子的块级容器(例如 inline-blocks, table-cells, 和 table-captions),以及overflow值不为“visiable”的块级盒子,都会为他们的内容创建新的块级格式化上下文(block formatting context)。

请注意,BFC并不是一个css属性,也不是一段代码,而是css中基于box的一个布局对象,它是页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用。明确地,它是一个独立的盒子,并且这个独立的盒子内部布局不受外界影响,当然,BFC也不会影响到外面的元素。

成为BFC的条件

其实在w3c规范中已经简单罗列了称为BFC的基本条件,但我们还是详细说明下,保持记忆脉络清晰。

一个BFC是一个HTML盒子并且至少满足下列条件中的任何一个:

  1. float的值不为none
  2. position的值不为static或者relative
  3. display的值为 table-cell, table-caption, inline-block,flex, 或者 inline-flex中的其中一个
  4. overflow的值不为visible
  5. 根元素

BFC的特性

BFC的特性可以总结为以下几点:

  1. BFC内部,盒子由上至下按顺序进行排列,其间隙由盒子的外边距决定,并且,当同一个BFC中的两个盒子同时具有相对方向的外边距时,其外边距还会发生叠加(Margin Collapse)
  2. BFC内部,无论是浮动盒子还是普通盒子,其左总是与包含块的左边相接触
  3. BFC 区域不会与float box区域相叠加
  4. BFC内外布局不会相互影响
  5. 计算BFC高度的时候,浮动元素的高度也计算在内

触发BFC

根据成为BFC的条件,一般有以下4种方法触发BFC:

  1. display: table 前后带有换行符,我们一般也不常用
  2. overflow: scroll 可能会出现不想要的滚动条,丑
  3. float: left 万一我们不想让元素浮动呢?
  4. overflow: hidden 比较完美的创建BFC的方案,副作用较小,仿佛遇到了我的心动女生

BFC能解决的问题

1. 解决margin collapse(外边距叠加)

什么是外边距叠加?复述一遍:

同一个BFC中的两个盒子同时具有相对方向的外边距时,外边距会发生叠加(Margin Collapse),当兄弟盒子的外边距不一样时,将以最大的那个外边距为准。

如上述展示,我们将内部灰色盒子的垂重margin设置为和自身高度一样,按自然思维两个盒子之间的距离应该是两个盒子的高度,由于外边距叠加,只剩下一个身位的高度。

要解决上述问题,设想:如果他们属于不同的BFC,他们之间的外边距将不会折叠。我们给其中的一个盒子外部包裹一层父盒子,并成为一个BFC。

现在可以清楚地看到,第一个盒子由于不再和其他其他同类名盒子在同一个BFC中,它和第二个盒子的外边距并没有发生叠加

总的来讲,外边距叠加本身是由BFC引起的,但是现在我们要用BFC来解决这个问题,颇有点以毒攻毒的味道。

2.清除浮动

想想那些年我们一起清除过的浮动,解决方式是什么?clear: both?父元素一起浮动?这些都没错,但是作为前端开发者,我们解决问题应该需要掌握多种技能,以适应多种不同的问题环境,偶尔还可以装装X:)

我们往往会遇到这样一种情况,父元素高度自适应,子元素浮动,因为不在同一文档流中,父元素的高度会坍塌,如下所示:

这个时候,我们可以利用BFC来解决问题,根据是:计算BFC高度的时候,浮动元素的高度也计算在内

我们通过添加overflow: hidden,在容器中创建一个新的BFC,效果如下:

只需要添加一个属性,效果不错吧~

3.实现两栏布局

一般的后台管理系统,很多都是传统的左菜单右内容的两栏布局,我们经常会选择左栏浮动,右边设置左padding或者margin的思路来实现这一做法,其实利用BFC也可以创建两栏布局,根据是:BFC 区域不会与float box区域相叠加

See the Pen XpLJXm by junnan shi (@BenjaminShih) on CodePen.

简单吧~

结尾

前端知识网络错综复杂,包括各种hack和黑科技,难免疏漏,或有不对之处,欢迎交流