块格式化上下文(BFC)
一、 前言
BFC的介绍到处都是,写这个纯属是看别人写的难受,不知所言。
二、 什么是BFC
是 Web 页面的可视 CSS 渲染的一部分,是块级盒子的布局过程发生的区域,也是浮动元素与其他元素交互的区域。 ——来自MDN
首先这一段比较官方的话,理解起来就很玄乎了。是web页面css渲染的一部分,也就是说这是既定的渲染机制的组成部分,在css渲染过程中也一定会基于它的规则来进行渲染;是块级盒子布局过程发生的区域,也是浮动元素与其他元素交互的区域,表明我们在使用块级盒子布局或者设置浮动的场景中会存在这样一个区域。而这个区域是有特定的渲染规则的。
总的来说就是,BFC定义了一个有着特定渲染规则的区域。那我们的重点只要了解,这个区域是什么样的一个区域,它的渲染规则是怎么样的?
三、 BFC怎么出现的
● 根节点:html
● 非溢出可见节点:overflow值不为visible、clip的块元素
● 浮动节点:float:left/right
● 绝对定位节点:position:absolute/fixed
● 设置了多列的容器:column-count或column-width值不为auto
● 被定义为块级的非块级节点:
display:inline-block/flow-root/table-cell/table-caption/flex/inline-flex/grid/inline-grid
注意,这里介绍一下,在实际的页面布局当中,如果我们把一个元素节点设置了除了上述的第一的其他属性之一,这个节点范围内就形成了一个BFC。
四、 渲染规则
1、 BFC是一个隔离且不受外界影响的独立区域,容器中的子节点不会在布局中影响到外面的节点,外面也不会影响里面
2、 BFC不会与同级浮动区域重叠
3、 BFC在计算高度时其浮动子节点也会参与
五、 BFC的作用
BFC的作用要结合它的渲染规则来看,第三点介绍如果我们把一个元素节点设置了形成BFC的属性后,这个节点范围内就形成了一个BFC。那为何要让它形成BFC呢?那一定是基于业务进行页面布局的需要。因此,下面介绍一下我们常见布局中那些场景是需要借助BFC来解决问题的。
1、 关于元素在页面中的布局
● 标准流
元素按照在HTML中先后位置自上而下布局;行内元素水平排列,直到被占满一行后换行;块级元素默认占满一行;所有的元素默认是标准流布局。
● 浮动
浮动的元素脱离正常的文档流,向左或者向右浮动
● 绝对定位
元素会整体脱离正常的文档流,定位是相对于离元素最近的设置了绝对或相对定位的父元素决定的。如果没有父元素设置绝对或相对定位,则元素相对于根元素即html元素定位。
2、 BFC使用场景
通过设置属性来形成BFC的情况下,需要注意的时添加的该属性是否会带来副作用。因为每一个属性都是有自己的原作用的,比如overflow: hidden;子元素超出父级范围将隐藏。要形成BFC,大部分情况都可以使用display:flow-root;将不会有任何副作用。
● 清除因浮动带来的父级元素高度塌陷
<div class="bg">
<div class="box-wrap">
<div class="box-1"></div>
<div class="box-2">hello</div>
</div>
<div class="block-box"></div>
</div>
.bg {
border:1px solid red;
}
.box-wrap {
float:left;
border:1px solid #000;
}
.box-1 {
width:100px;
height:100px;
background-color:rgba(0,0,0,.6);
}
.box-2 {
width:200px;
height:50px;
background-color:orange;
display:flow-root
}
.block-box {
height:100px;
background-color:lightgreen;
}
可以看到在box-wrap盒子浮动之后,bg盒子的实际高度时以block-box的高度为主的。box-wrap脱离了正常的文档流,不参与父元素的高度计算(父元素没有设置高度)。
解决:可以给bg盒子添加可以让其形成BFC的属性overflow: auto或者display:flow-root
原理:BFC在计算高度时其浮动子节点也会参与
● 清除浮动元素带来的影响
.bg {
border:1px solid red;
}
.box-wrap {
border:1px solid #000;
}
.box-1 {
width:100px;
height:100px;
float:left;
background-color:rgba(0,0,0,.6);
}
.box-2 {
width:200px;
height:50px;
background-color:orange;
}
.block-box {
height:100px;
background-color:lightgreen;
}
box-1盒子浮动之后,脱离了正常文档流,因此后面的元素会占据它的位置。但是box-2和block-box都会与box-1发生重叠。如果,分别给box-2和block-box加上display:flow-root,则会变成这样:
原理:BFC不会与同级浮动区域重叠
● 防止垂直margin合并
在盒子模型中,垂直方向相邻的两个盒子会出现margin合并,合并情况如下:
1. 两个盒子相邻边的margin都为正值,取最大值
2. 两个盒子相邻边的margin都为负值,取最小值,两者会互相重合
3. 两个盒子相邻边的margin一正一负,取两者相加值,若结果为负,两者会互相重合
<div class="bg">
<div class="box-1"></div>
<div class="box-2">hello</div>
</div>
.bg {
border:1px solid red;
}
.box-1 {
width:100px;
height:100px;
margin-bottom:10px;
background-color:lightgreen;
}
.box-2 {
width:100px;
height:100px;
margin-top:20px;
background-color:orange;
display:flow-root;
}
可以看到box1和box-2的边距是20px,如果要避免这种情况,可以让其中一个元素被包在BFC中,这样就可以做到互不影响了
<div class="bg">
<div class="box-wrap">
<div class="box-1"></div>
</div>
<div class="box-2">hello</div>
</div>
.bg {
border:1px solid red;
}
.box-wrap {
display:flow-root;
}
.box-1 {
width:100px;
height:100px;
margin-bottom:10px;
background-color:lightgreen;
}
.box-2 {
width:100px;
height:100px;
margin-top:20px;
background-color:orange;
display:flow-root;
}
这样,两个盒子之间的边距就是30px了
原理:BFC是一个隔离且不受外界影响的独立区域,容器中的子节点不会在布局中影响到外面的节点,外面也不会影响里面
六、 总结
在实际页面布局中,是可以借助BFC来达到想要的效果,比如可以通过浮动,BFC等来实现两列布局,但是实际上使用flex更加建议。形成BFC很简单,关键点在于你设置属性时需要考虑时候带来副作用。
转载自:https://juejin.cn/post/7186301553026793527