1. 概念
BFC(Block formatting context)直译为"块级格式化上下文"。它是一个独立的渲染区域,只有Block-level box参与, 它规定了内部的Block-level Box如何布局,并且与这个区域外部毫不相干。
在解释什么是BFC之前,需要先知道Box、Formatting Context的概念。
1.1 Box
Box 是 CSS 布局的对象和基本单位,一个页面是由很多个 Box 组成的。元素的类型和display属性决定了这个Box的类型。 不同类型的Box,会参与不同的Formatting Context(一个决定如何渲染文档的容器),因此Box内的元素会以不同的方式渲染。
- block-level box:display 属性为 block, list-item, table 的元素,会生成 block-level box。并且参与 block fomatting context;
- inline-level box:display 属性为 inline, inline-block, inline-table 的元素,会生成 inline-level box。并且参与 inline formatting context;
- run-in box: css3中的概念。
1.2 Formatting Context
页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用。最常见的 Formatting context 有 Block fomatting context (简称BFC)和 Inline formatting context (简称IFC)。
2. 布局规则
- 内部的Box会在垂直方向,一个接一个地放置(即块级元素独占一行)。
- BFC的区域不会与float box重叠(利用这点可以实现自适应两栏布局)。
- 内部的Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠(margin重叠三个条件:同属于一个BFC;相邻;块级元素)。
- 计算BFC的高度时,浮动元素也参与计算。
- BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
3. 创建BFC
- float left/right
- overflow的值不是visiable
- display table-cell/table-caption/inline-block-inline-flex/flex
- position的值不是static或者relative
4. 作用
4.1 解决margin塌陷/重叠问题
什么是margin的塌陷和重叠?塌陷是父子元素之间没有border/padding等内容时发生,重叠是兄弟元素之间垂直方向上发生。
4.1.1 父子元素塌陷
比如父元素包着一个子元素,会发现父子元素的上下边距合并为了一个外边距:
#parent {
width: 200px;
height: 100px;
background-color: lightgreen;
margin: 20px auto;
/* display: flex; */
}
.children {
width: 50px;
height: 50px;
background-color: lightcyan;
margin: 20px auto;
}
<div id="parent">
<div class="children"></div>
</div>
现在通过激活父元素的BFC,解决margin塌陷问题:
#parent {
width: 200px;
height: 100px;
background-color: lightgreen;
margin: 20px auto;
display: flex;
}
4.1.2 兄弟元素重叠
两个p元素之间距离本该为200px,现在实际上只有100px,发生了margin重叠。
<style>
p {
background: #888;
width: 200px;
height: 100px;
margin: 100px;
}
</style>
<body>
<p>ABC</p>
<p>abc</p>
</body>
可以通过在p外面包裹一层容器div,并触发生成BFC,那么两个P便不属于同一个BFC,就不会发生margin重叠问题了。
<style>
p {
background: #888;
width: 200px;
height: 100px;
margin: 100px;
}
div{
overflow: hidden;
}
</style>
<body>
<p>ABC</p>
<div>
<p>abc</p>
</div>
</body>
4.2 清除浮动
4.2.1 BFC清除浮动
子元素不设置浮动的情况下,当父元素不设置高度时,其高度会被子元素撑开。但是当子元素设为浮动元素时,由于子元素脱离了文档流,子元素原本的位置空间不被保留导致父元素高度为0,这就是高度塌陷现象。此时需要清除浮动:
<style>
.father {
border: 5px solid lightgreen;
/* 激活父元素BFC清除浮动 */
overflow: hidden;
}
.left {
float: left;
}
</style>
<body>
<div class="father">
<div class="left">我是float:left</div>
</div>
</body>
4.2.2 伪元素清除浮动
这里顺便提一下剩下两种常用的清除浮动方式:
<style>
.div1 {
border: 5px solid lightgreen;
}
.div2 {
height: 100px;
width: 200px;
background-color: lightblue;
float: left;
}
/* 方法一 */
.clearfix::after {
content: "";
display: block;
clear: both;
// 下面这两行似乎不一定要加
visibility: hidden;
height: 0;
}
/* 方法二 可以更好解决外边距重叠问题*/
.clearfix::after,
.clearfix::before {
content: "";
display: block;
clear: both;
}
</style>
<body>
<div class="div1 clearfix">
<div class="div2">div2</div>
</div>
</body>
4.3 实现两栏布局
实现左侧定宽,右侧自适应。如果不激活右侧div的BFC,左侧浮动起来的div会把右侧div盖住。因此需要激活右侧BFC:
<style>
.div1 {
width: 100px;
height: 150px;
float: left;
background: rgb(139, 214, 78);
}
.div2 {
height: 300px;
background-color: aquamarine;
/* 激活BFC */
overflow: hidden;
}
</style>
<body>
<div class="div1">我是div1</div>
<div class="div2">我是div2</div>
</body>