作者:滴滴公共前端团队 - 邱莲
BFC是什么?
BFC(Block Formatting Context)直译为“块级格式化范围”。
是 W3C CSS 2.1 规范中的一个概念,它决定了元素如何对其内容进行定位,以及与其他元素的关系和相互作用。当涉及到可视化布局的时候,Block Formatting Context提供了一个环境,HTML元素在这个环境中按照一定规则进行布局。一个环境中的元素不会影响到其它环境中的布局。
比如浮动元素会形成 BFC,浮动元素内部子元素的主要受该浮动元素影响,两个浮动元素之间是互不影响的。这里有点类似一个 BFC 就是一个独立的行政单位的意思。
也可以说 BFC 就是一个作用范围。可以把它理解成是一个独立的容器,并且这个容器的里box的布局,与这个容器外的毫不相干。
BFC 的特征:
内部的Box会在垂直方向,一个接一个地放置。
Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠
每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
BFC的区域不会与float box重叠。
BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
计算BFC的高度时,浮动元素也参与计算
BFC 的应用场景有哪些?如何触发 BFC?
满足下列条件中至少一项,即可触发 BFC:
float 的值不为none。
position 的值不为static或者relative。
display的值为 table-cell, table-caption, inline-block, flex, 或者 inline-flex中的其中一个。
overflow的值不为visible。
BFC 的应用场景:
1.解决 margin
叠加问题:
<div class="first-block"></div>
<div class="second-block">
<h2>DDFE</h2>
</div>
.first-block {
background: #F44336;
width: 200px;
height: 200px;
}
.second-block {
background: #00BCD4;
width: 200px;
height: 200px;
}
很简单是吧,浏览器中的效果是这样的:
为什么 first-block 和 second-block 之间会有这么宽的间距?
原因是:外边距折叠,这个间距是 h2 的上外边距引起的。
CSS 里面关于折叠的条件:
两个块元素要产生折叠现象,必须满足一个必备条件:这两个元素的 margin 必须是 相邻 的;那么如果定义相邻呢,w3c 规范,两个 margin 是邻接的必须满足以下条件:
必须是处于常规文档流(非float和绝对定位)的块级盒子,并且处于同一个 BFC 当中。
没有inline盒子,没有空隙,没有 padding 和 border 将他们分隔开。
都属于垂直方向上相邻的外边距,可以是下面任意一种情况:
那么我们就可以通过给元素叫边框或者边距来解决啦,我是不是狠聪明呢?
解决办法 1:
折叠问题解决了,但是由于有1px的边框,second-block 看起来会比 first-block 宽一点,没关系,添加 box-sizing: border-box
属性可以解决这个问题:再加一句:box-sizing:border-box
;
解决办法 2:
通过把 overflow 把 second-block 元素形成一个 BFC,完美解决!
2.用于布局
杯布局和双飞翼布局,他们的都要求三列布局,中间宽度自适应,两边定宽,这样做的优势是重要的东西放在文档流前面可以优先渲染。
样子,就长这样:
老规矩先贴上代码:
html部分:
css部分:
- html代码中,middle部分首先要放在container的最前部分,然后是left,right 。
- 将三者都设置
float:left
,position:relative
。 - middle设置
width:100%
占满一行 。 - 此时middle占满一行,所以要把left拉到middle所在行的最左边,使用
margin-left:-100%
。 - 这时left拉回到middle所在行的最左边,但会覆盖middle内容的左端,要把middle内容拉出来,所以在外围container加上
padding:0 200px
。 - middle内容拉出来了,但left也跟着出来了,所以要还原,就对left使用相对定位
left:-200px
。 - 同理,right要拉到middle所在行的最右边,使用
margin-left:-200px
,right:-200px
。
其实除了圣杯布局还有一个双飞翼布局,双飞翼布局是对圣杯布局的一种改良,多一个div就可以不用相对布局了,只用到了浮动和负边距。
DOM结构:container内层增加了一个div
样式:去掉了左右栏的相对定位,去掉包裹层padding,以中间栏新增div的margin代替。
是不是很简单?
3.用于清除浮动,计算BFC高度
举个例子:
我们想象中应该是这样的:
但实际是却是这样的:
div 标签没有包住 ul 标签,原因很简单:container 下的子元素浮动了,因此div的高度就塌陷了。
要解决塌陷,就得清除浮动。
清除浮动就两种方式:
1)利用 clear
属性清除浮动。
2)使父容器形成 BFC。
给父元素 .container
加一句 overflow:hidden
触发 bfc。
欢迎关注DDFE
GITHUB:github.com/DDFE
微信公众号:微信搜索公众号“DDFE”或扫描下面的二维码