前端必知必会-BFC案例剖析
简介
在说 BFC
之前,我们先来了解一下标准文档流,标准文档流是指在页面中所有的元素按照从左到右,从上到下这样的一个顺序来进行排列的。
这里的标准文档流其实就是格式化上下文( Formatting Context
),那么什么又是格式化上下文呢,让我们接着往下看。
格式化上下文(Formatting Context)
格式化上下文,简单来说就是一个独立的渲染区域,在这个渲染区域中的元素会按照它的一个渲染规则来进行排列。
标准文档流中的盒子其实就是格式化上下文,只不过它包括块级格式化上下文以及行级格式化上下文,不同格式化上下文的渲染规则不同,它决定了它的子元素按照什么样的规则来排列,以及和其他元素的关系和相互作用。这里需要注意的就是不同的格式化上下文所针对的元素种类也不同。
常见的格式化上下文有以下四种。
- 【Block formatting context】 BFC 块级格式化上下文
这里的BFC就是我们今天的重点,BFC只针对块级元素
- 【Inline formatting context】(IFC) 行级格式化上下文
IFC只针对行级元素
- 【Grid formatting context】(GFC) 网格布局格式化上下文
我们可以在网格容器上定义网格行和网格列
- 【Flex formatting context】(FFC) 自适应格式上下文
当我们使用
Flex
弹性盒子布局实际上就是声明创建了FFC
什么是BFC?
说了那么多的废话终于到我们今天的主题了,相信看了上面的一些介绍大家应该对 BFC
多多少少有一些了解了吧。
没错, BFC
块级格式化上下文,页面中独立的一块渲染区域,只作用于块级元素,内部的所有块级元素会按照它的一套渲染规则来排列。
如何创建BFC?
既然知道 BFC
是什么了,那么如何创建一个 BFC
呢?
我们来看看 w3c
对 BFC
的定义
Floats, absolutely positioned elements, block containers (such as inline-blocks, table-cells, and table-captions) that are not block boxes, and block boxes with 'overflow' other than 'visible' (except when that value has been propagated to the viewport) establish new block formatting contexts for their contents.
看不懂没关系,我们来简单的罗列一下。只要满足下面的任何一个条件都可以触发 BFC
。
body
根元素- 浮动元素:
float
除none
以外的值 - 绝对定位元素:
position
(absolute、fixed
) display
为inline-block、table-cells、flex
overflow
除了visible
以外的值 (hidden、auto、scroll
)
BFC特性
说了这么多东西,那么有的人可能会问了,BFC
到底可以用来干什么呢,或者说它可以解决什么问题,当我们了解了它的特性就会清楚了。
- 内部的
Box
会在垂直方向上一个接一个的放置 - 块级格式化上下文中相邻的盒子之间的垂直边距折叠
- 每个元素的左外边距与包含块的左边界相接触(从左向右),即使浮动元素也是如此。(这说明
BFC
中子元素不会超出他的包含块,而position
为absolute
的元素可以超出他的包含块边界) - BFC的区域不会与
float
的元素区域重叠 - 计算
BFC
的高度时,浮动子元素也参与计算 BFC
就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面元素,反之亦然
BFC的作用及会产生的问题
上下margin合并
.box1{ width: 200px; height: 200px; background: cyan; margin-bottom: 30px; text-align: center; } .box2{ width: 200px; height: 200px; margin-top: 20px; background: cyan; text-align: center; }
<div class="box1">第一个盒子</div> <div class="box2">第二个盒子</div>
在上面的例子中我们可以看到,我们给第一个盒子设置下边距 30px
,第二个盒子上边距设置 20px
,按照理论来说,这两个盒子的实际间距应该为 30+20 也就是 50px
,但事实上是这两个盒子的距离只有 30px
,为什么呢。
首先我们的节点是添加在 body
下的,这时候其实已经创建了 BFC
的渲染区域,然后再来看 BFC
特性第二条,块级格式化上下文中相邻的盒子之间的垂直边距折叠,也就是说这时候的上下 margin
发生了重叠,并且只会选用较大的 margin
。
那么怎么解决这个问题呢,这时候我们只要给其中一个元素创建一个 BFC
的渲染区域就可以,为什么?我们来看 BFC
特性最后一条,每个 BFC
都是独立的,不会与外界元素互相影响。我们直接给 box2
上添加一个 position: absolute
就可以了
高度塌陷
.box{ background: red; } .item{ width: 100px; height: 100px; float: left; }
<div class="box"> <div class="item">内部的盒子</div> </div>
这个问题应该遇到的会比较多点,子元素浮动之后撑不开父元素的高度,这时候我们给父元素创建一个 BFC
就可以了。运用的是 BFC
特性的第5条,计算BFC的高度时,浮动子元素也会计算。我们这里给父元素添加一个 overflow:hidden
这时候父元素的高度就会有了。
其实还有其他一些由于 BFC
引发的问题,由于时间原因,这里我就不一一举例了,有兴趣的朋友可以把其他情况通过邮箱告诉我,我会添加上去。