1、什么是BFC以及如何创建BFC
(1)BFC 的概念:
BFC(Block formatting context),即块级格式化上下文,它作为 HTML 页面上的一个独立渲染区域,只有区域内元素参与渲染,且不会影响其外部元素。
在一个 Web 页面的 CSS 渲染中,块级格式化上下文 (Block Fromatting Context)是按照块级盒子布局的。
(2)W3C 对 BFC 的定义如下:
浮动元素和绝对定位元素,非块级盒子的块级容器(例如 inline-blocks,table-cells 和 table-captions),以及 overflow 值不为 “visiable”
的块级盒子,都会为他们的内容创建新的 BFC(块级格式上下文)。
(3)如何创建BFC,即BFC的触发条件:
- 根元素,即 HTML 元素。
- float 除了 none 以外的值。
- position 的值为 absolute 或 fixed,不是 static 或者 relative。
- display 的值是 inline-block、table-cell、flex、table-caption或者 inline-flex 。
- overflow 除了 visible 以外的值(hidden,auto,scroll ) 。
创建一个 BFC 是非常简单的,只要满足上述 5 个 CSS 条件之一就行。
2、BFC 的布局规则
-
BFC 就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
-
内部的 Box 会在垂直方向,一个接一个地放置。
-
Box 垂直方向的距离由 margin 决定。属于同一个 BFC 的两个相邻 Box 的 margin 会发生重叠。
-
每个盒子(块盒与行盒)的 margin box 的左边,与包含块 border box 的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
-
BFC 的区域不会与 float box重叠(可以用此来解决自适应布局的问题)。
-
计算 BFC 的高度时,浮动元素也参与计算(撑开父元素,不会出现高度塌陷问题)。
3、BFC 的应用
BFC 一般用来解决以下几个问题:
- 利用 BFC 避免外边距重叠
- 利用 BFC 清除浮动
- 自适应两栏布局
3.1 利用 BFC 避免外边距重叠
根据 BFC 布局规则:Box 垂直方向的距离由 margin 决定,属于同一个 BFC 的两个相邻 Box 的 margin 会发生重叠。
折叠的结果:
- 两个相邻的外边距都是正数时,折叠结果是它们两者之间较大的值。
- 两个相邻的外边距都是负数时,折叠结果是两者绝对值的较大值。
- 两个外边距一正一负时,折叠结果是两者的相加的和。
解决方法:
- 当两个相邻块级子元素分属于不同的 BFC 时,就可以阻止margin 重叠。
操作方法:
- 给其中一个 p 外面包一个 div,然后通过触发外面这个 div 的 BFC,就可以阻止这两个 p 的 margin 重叠。
代码:
// HTML代码
<div class="box">
<p>段落1</p>
<p>段落2</p>
</div>
// CSS代码
<style>
.box {
background-color: aquamarine;
/* 创建了一个BFC */
overflow: hidden;
}
p {
background-color: seagreen;
margin: 10px 0;
}
</style>
效果:发生了外边距重叠
解决方法: 给其中一个 p 外面包一个 div,然后通过触发外面这个 div 的 BFC,就可以阻止这两个 p 的 margin 重叠。
// HTML代码
<div class="box">
<p>段落1</p>
<div class="box2">
<p>段落2</p>
</div>
</div>
// CSS代码
<style>
.box {
background-color: aquamarine;
/* 创建了一个BFC */
overflow: hidden;
}
p {
background-color: seagreen;
margin: 10px 0;
}
.box2 {
/* 创建了一个BFC */
overflow: hidden;
}
</style>
3.2 利用 BFC 清除浮动
浮动元素是会脱离文档流的(绝对定位元素会脱离文档流)。如果一个没有高度或者 height 是 auto 的容器的子元素是浮动元素,则该容器的高度是不会被撑开的。我们通常会利用伪元素(:after
或者:before
)来解决这个问题。BFC 能包含浮动,也能解决容器高度不会被撑开的问题。
看一个例子:
// HTML代码
<div class="container">
<div>内容1</div>
<div>内容2</div>
</div>
// CSS代码
<style>
.container {
background-color: skyblue;
}
.container div {
float: left;
background-color: steelblue;
margin: 10px;
}
</style>
效果:
在上面这个例子中,容器没有任何高度,并且它包不住浮动子元素,容器的高度并不会被撑开。为解决这个问题,可以在容器中创建一个BFC:
<style>
.container {
/* 创建了一个BFC */
overflow: hidden;
background-color: skyblue;
}
.container div {
float: left;
background-color: steelblue;
margin: 10px;
}
</style>
效果:
现在容器可以包住浮动子元素,并且其高度会扩展至包住其子元素,在这个新的 BFC 中浮动元素又回归到页面的常规流之中了。
3.3 自适应两栏布局
根据:每个盒子的 margin box 的左边,与包含块 border box 的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
// HTML代码
<div class="box">
<div class="left">左边固定宽度为200px</div>
<div class="right">右边自适应</div>
</div>
// CSS代码
<style>
.box {
background-color: pink;
height: 300px;
}
.left {
float: left;
width: 200px;
height: 200px;
background-color: royalblue;
}
.right {
height: 300px;
background-color: skyblue;
}
</style>
效果:
又因为:BFC 的区域不会与 float box 重叠。
所以我们让 right 单独成为一个 BFC,right 会自动的适应宽度,这样就可以实现自适应两栏布局效果了。
<style>
.box {
background-color: pink;
height: 300px;
}
.left {
float: left;
width: 200px;
height: 200px;
background-color: royalblue;
}
.right {
/* 创建了一个BFC */
overflow: hidden;
height: 300px;
background-color: skyblue;
}
</style>
效果: