A block formatting context is a part of a visual CSS rendering of a Web page. It is the region in which the layout of block boxes occurs and in which floats interact with other elements.
什么是 BFC
BFC 全称是 block formatting context,翻译成中文就是块级格式化上下文。在很多 CSS 教程中,很少有直接提到 BFC 的。那这是不是说明 BFC 不重要呢?其实不是的,BFC 在有些地方有着很大的作用。
BFC 的特点
Block formatting contexts are important for the positioning (see float) and clearing (see clear) of floats.The rules for positioning and clearing of floats apply only to things within the same block formatting context.
BFC 主要特点:
- Floats do not affect the layout of the content inside other block formatting contexts, and clear only clears past floats in the same block formatting context.
- Margin collapsing also occurs only between blocks that belong to the same block formatting context.
如何创建 BFC
A block formatting context is created by at least one of the following:
- the root element or something that contains it
- floats (elements where float is not none)
- absolutely positioned elements (elements where position is absolute or fixed)
- inline-blocks (elements with display: inline-block)
- table cells (elements with display: table-cell, which is the default for HTML table cells)
- table captions (elements with display: table-caption, which is the default for HTML table captions)
- anonymous table cells implicitly created by the elements with display: table, table-row, table-row-group, table-header-group, table-footer-group (which is the default for HTML tables, table rows, table bodies, table headers and table footers, respectively), or inline-table
- block elements where overflow has a value other than visible
- display: flow-root
- elements with contain: layout, content, or strict
- flex items (direct children of the element with display: flex or inline-flex)
- grid items (direct children of the element with display: grid or inline-grid)
- multicol containers (elements where column-count or column-width is not auto, including elements with column-count: 1)
上面基本上列出了创建 BFC 的全部方式,但是我们不可能也不必要每种方式都记住。
我们常用的主要有以下方式:
- overflow 不为 visible
- position 设置为绝对定位(包括 absolute 和 fixed)
- float 不为 none
- display 设置为 inline-block、table-cell、table-caption、flex 等
BFC 应用场景
清除浮动
<body>
<h1>清除浮动</h1>
<div class="container">
<div class="left">左侧栏: Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum. </div>
<div class="right">右侧栏:Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>
</div>
<div class="footer">
<p>底部底部底部底部底部底部底部底部底部</p>
</div>
</body>
h1 {
margin: 10px 0;
text-align: center;
}
.left {
width: 400px;
float: left;
background-color: #f00;
}
.right {
width: 400px;
float: left;
background-color: #0f0;
}
如图所示,由于内容元素设置了 float 属性,导致底部的元素没有另起一行渲染,而是直接跟在了第二个内部元素的后面。当我们为父元素设置 BFC 后,就能解决这个问题。
h1 {
margin: 10px 0;
text-align: center;
}
.container {
overflow: hidden; // 设置 BFC
}
.left {
width: 400px;
float: left;
background-color: #f00;
}
.right {
width: 400px;
float: left;
background-color: #0f0;
}
只要设置 BFC 就能清除浮动了。不过这样清除浮动会有副作用,所以一般全局的清除浮动样式不会这样写,不过在某些地方还是可以直接使用的。有兴趣看一看 bootstrap 的全局清除浮动样式,戳这里查看
防止外边距重叠
外边距重叠有两种现象,不过都可以使用 BFC 来解决。
子元素与子元素
<h1>子元素与子元素</h1>
<div class="container">
<div class="top">大明: Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum. </div>
<div class="bottom">小明:Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>
</div>
h1 {
margin: 10px 0;
text-align: center;
}
.top {
margin-bottom: 100px;
background-color: #f00;
}
.bottom {
margin-top: 50px;
background-color: #0f0;
}
这里给上面的子元素设置了 margin-bottom,给下面的子元素设置了 margin-top,但是最终两个元素之间的间隔不是 100 + 50 后的 150,而是 100。原因是因为发生了 margin collapsing,这不是一个 bug,而是 w3c 的一个规定。但是有时候我们并不需要这个特性,那如何解决呢?
其中一个方法就是利用 BFC,给第二个元素设置 position 的值为 absolute/fixed 或 float:left。
h1 {
margin: 10px 0;
text-align: center;
}
.top {
margin-bottom: 100px;
background-color: #f00;
}
.bottom {
margin-top: 50px;
position: absolute; // 设置 BFC
background-color: #0f0;
}
子元素与父元素
<div class="container">
<div class="box">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>
</div>
h1 {
margin: 10px 0;
text-align: center;
}
.container {
height: 300px;
background-color: #0f0;
}
.box {
margin-top: 100px;
background-color: #f00;
}
这里将子元素的 margin-top 设置为了 100px,但现象是父元素的生效了,并我们预想的子元素距父元素的上边 100px。这里也是发生了 margin collapsing 外边距塌陷。
解决方法之一和上面一样,利用 BFC。我们只需要给父元素加一个 overflow: hidden;
即可。
h1 {
margin: 10px 0;
text-align: center;
}
.container {
height: 300px;
overflow: hidden; // 设置 BFC
background-color: #0f0;
}
.box {
margin-top: 100px;
background-color: #f00;
}
更多 margin collapsing 戳这里查看