一、什么是 BFC
BFC全称Block Formatting Context, 中文可译为块级格式化上下文- 对于浮动元素、绝对定位元素、非块级盒子的块级容器(
inline-block、table-cells、table-captions)、overflow值不为visiable的块级盒子, 容器内部将创建新的BFC - 具备
BFC特性的元素, 内部将形成独立的渲染区域, 可以看成是一个容器, 容器内的元素和外部元素互不影响 - 在
BFC内, 块容器从顶端开始垂直地一个接一个地排列, 两个容器之间的垂直的间隙是由他们的margin值所决定的, 在同一个BFC中, 两个相邻的块级盒子的垂直外边距会产生折叠, 注意这里说的是块级盒子是指display的值为block的块级容器, 如果一个容器是block一个是inline-block那么他们的margin是不会发生折叠(下面将会进行详细描述)
二、如何触发 BFC
- 根元素
<html>自带BFC特性 float属性值不为noneoverflow属性值不为visible(默认值)display属性值为table-celltable-captioninline-blockflow-root中的任何一个position属性值不为relative和static
三、BFC 特性(应用场景)
3.1 BFC 内容器排列规律
BFC里面的容器都会以垂直方向排列, 并且两个相邻块级容器的上下margin会发生重叠
<style>
.box{
width: 100px;
height: 100px;
margin: 20px;
border: 2px solid red;
}
.parent {
display: flow-root;
}
</style>
<div class="parent">
<div class="box"></div>
<div class="box"></div>
</div>
BFC内margin值合并只针对两个块级容器(display的值为block), 如下例子一个容器是block一个是inline-block那么他们的margin是不会发生合并
<style>
.box{
width: 100px;
height: 100px;
margin: 20px;
border: 2px solid red;
}
.box1 {
display: inline-block;
}
.parent {
display: flow-root;
}
</style>
<div class="parent">
<div class="box box1"></div>
<div class="box"></div>
</div>
- 上面例子中
box1设置了display: inline-block会触发了box1容器的BFC, 但是box1容器是否触发BFC并不会影响margin的合并, 主要是因为margin的合并现象只针对块级容器, 下面例子将display: inline-block修改为overflow: hidden;同样触发了box1容器BFC,margin依然发生重叠
<style>
.box{
width: 100px;
height: 100px;
margin: 20px;
border: 2px solid red;
}
.box1 {
overflow: hidden;
}
.parent {
display: flow-root;
}
</style>
<div class="parent">
<div class="box box1"></div>
<div class="box"></div>
</div>
3.2 BFC 解决 margin 穿透问题
依据: 当容器触发
BFC那么该容器就将是独立的渲染控件, 容器内外元素不会相互影响
margin穿透现象: 如下演示代码, 子元素设置了margin但是margin并没有作用与父元素(和父元素间没有产生间距), 而是作用于父元素相邻的元素上
<style>
.parent {
background: rgba(255, 0, 0, 0.5);
}
.child {
width: 100px;
height: 100px;
margin-top: 50px;
background: rgba(0, 255, 0, 0.5);
}
</style>
<div>这是和父元素相邻的元素</div>
<div class="parent">
<div class="child"></div>
</div>
- 解决办法: 为父元素创建
BFC, 如此容器内外元素就不会产生干扰
补充:
BFC并不是解决margin穿透的唯一方法, 还可以通过为父元素设置border、padding等方法来解决margin穿透
<style>
.parent {
display: flow-root;
background: rgba(255, 0, 0, 0.5);
}
.child {
width: 100px;
height: 100px;
margin-top: 50px;
background: rgba(0, 255, 0, 0.5);
}
</style>
<div>这是和父元素相邻的元素</div>
<div class="parent">
<div class="child"></div>
</div>
3.3 BFC 解决子元素浮动, 容器高度塌陷问题
- 当子元素发生浮动的情况下, 浮动元素不再参与父元素高度的计算
<style>
.parent {
background: rgba(255, 0, 0, 0.5);
}
.child {
float: left;
width: 100px;
height: 100px;
background: rgba(0, 255, 0, 0.5);
}
</style>
<div class="parent">
parent
<div class="child"></div>
</div>
- 解决办法: 触发父容器
BFC, 浮动元素将会参与父元素高度的计算
<style>
.parent {
display: flow-root;
background: rgba(255, 0, 0, 0.5);
}
.child {
float: left;
width: 100px;
height: 100px;
background: rgba(0, 255, 0, 0.5);
}
</style>
<div class="parent">
parent
<div class="child"></div>
</div>
3.4 解决兄弟容器和浮动元素重叠问题
- 当容器进行浮动时, 该浮动容器将和其兄弟容器进行重叠
<style>
.parent {
background: rgba(255, 0, 0, 0.5);
}
.float {
float: left;
width: 100px;
height: 100px;
background: rgba(0, 255, 0, 0.5);
}
</style>
<div class="parent">
<div class="float"></div>
<div class="content">
在 `BFC` 内, 块容器从顶端开始垂直地一个接一个地排列,
两个容器之间的垂直的间隙是由他们的 `margin` 值所决定的,
在同一个 `BFC` 中, 两个相邻的 `块级盒子` 的垂直外边距会产生折叠,
注意这里说的是 `块级盒子` 是指 `display` 的值为 `block` 的块级容器,
如果一个容器是 `block` 一个是 `inline-block` 那么他们的 `margin`
是不会发生折叠(下面将会进行详细描述)
</div>
</div>
- 解决办法: 只需要触发兄弟容器(非浮动容器)的
BFC就能够解决重叠问题, 实现自适应双栏布局
<style>
.parent {
background: rgba(255, 0, 0, 0.5);
}
.float {
float: left;
width: 100px;
height: 100px;
background: rgba(0, 255, 0, 0.5);
}
.content {
display: flow-root;
}
</style>
<div class="parent">
<div class="float"></div>
<div class="content">
在 `BFC` 内, 块容器从顶端开始垂直地一个接一个地排列,
两个容器之间的垂直的间隙是由他们的 `margin` 值所决定的,
在同一个 `BFC` 中, 两个相邻的 `块级盒子` 的垂直外边距会产生折叠,
注意这里说的是 `块级盒子` 是指 `display` 的值为 `block` 的块级容器,
如果一个容器是 `block` 一个是 `inline-block` 那么他们的 `margin`
是不会发生折叠(下面将会进行详细描述)
</div>
</div>
- 补充: 上面例子中如何设置两个容器的间距
- 为浮动容器设置
margin-right - 为非浮动容器设置
padding-left - 为非浮动容器设置
margin-left, 主要这里的属性值要大于浮动容器宽度才有效果, 所以这里不推荐该方法
<style>
.parent {
background: rgba(255, 0, 0, 0.5);
}
.float {
float: left;
width: 100px;
height: 100px;
background: rgba(0, 255, 0, 0.5);
/* margin-right: 20px; */
}
.content {
display: flow-root;
/* padding-left: 20px; */
margin-left: 120px;
}
</style>
<div class="parent">
<div class="float"></div>
<div class="content">
在 `BFC` 内, 块容器从顶端开始垂直地一个接一个地排列,
两个容器之间的垂直的间隙是由他们的 `margin` 值所决定的,
在同一个 `BFC` 中, 两个相邻的 `块级盒子` 的垂直外边距会产生折叠,
注意这里说的是 `块级盒子` 是指 `display` 的值为 `block` 的块级容器,
如果一个容器是 `block` 一个是 `inline-block` 那么他们的 `margin`
是不会发生折叠(下面将会进行详细描述)
</div>
</div>
四、参考
大家好, 我是墨渊君, 如果您喜欢我的文章可以:
- 关注公众号: 「昆仑虚F2E」获取最新文章。
- GitHub: github.com/MoYuanJun
- 个人网站(昆仑虚, 虽然现在没啥东西): www.kunlunxu.cc