一、定义
MDN中是这样说的:块格式化上下文(Block Formatting Context,BFC) 是Web页面的可视化CSS渲染的一部分,是block块盒子的布局过程发生的区域,也是浮动float元素与其他元素交互的区域。
是不是看完之后,依然一脸懵逼.....反正我是(苦笑)。简单地说,BFC 就是一个独立容器,决定了元素如何对其内容进行定位,以及与其他元素的关系和相互作用,只不过这个属性不能被开发者显式的修改。
二、布局规则
- 内部的Box会在垂直方向,一个接一个地放置。
- Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠
- 每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
- BFC的区域不会与float box重叠。
- BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
- 计算BFC的高度时,浮动元素也参与计算
三、哪些元素会产生BFC?
- 根元素(
<html>
) - 浮动元素(元素的
float
不是none
) - 绝对定位元素(元素的
position
为absolute
或fixed
) - 行内块元素(元素的
display
为inline-block
) - 表格单元格(元素的
display
为table-cell
,HTML表格单元格默认为该值) - overflow的值不为visible(hidden、auto、scroll)
- 表格标题(元素的
display
为table-caption
,HTML表格标题默认为该值) - 匿名表格单元格元素(元素的
display
为table、
table-row
、table-row-group、
table-header-group、
table-footer-group
(分别是HTML table、row、tbody、thead、tfoot的默认属性)或inline-table
) display
值为flow-root
的元素contain
值为layout
、content
或 paint 的元素- 弹性元素(
display
为flex
或inline-flex
元素的直接子元素) - 网格元素(
display
为grid
或inline-grid
元素的直接子元素) - 多列容器(元素的
column-count
或column-width
不为auto,包括
column-count
为1
) column-span
为all
的元素始终会创建一个新的BFC,即使该元素没有包裹在一个多列容器中(标准变更,Chrome bug)。
四、经典用法
1、解决父子元素margin塌陷问题
<style>
body {
background: wheat;
}
.parent {
height: 500px;
width: 60%;
background: aqua;
}
.child {
height: 200px;
width: 200px;
padding: 20px;
border: 1px red solid;
margin: 30px;
background: yellow;
}
</style>
<body>
<div class="parent">
<div class="child"></div>
</div>
</body>
子元素内设置的margin会对父元素也造成影响,效果如下:
解决方法:
给父元素设置如下属性:
- overflow:hidden(常用)
- position:absolute/fixed
- display:table
- display:inline-block;
- float:left/right;
2、解决同级box垂直方向外边距合并问题
<style>
body {
background: wheat;
}
.parent {
height: 500px;
width: 60%;
background: aqua;
}
.child {
height: 200px;
width: 200px;
padding: 20px;
border: 1px red solid;
background: yellow;
margin: 30px;
}
</style>
<body>
<div class="parent">
<div class="child first"></div>
<div class="child"></div>
</div>
</body>
同级元素在垂直方向上外边距margin会重叠,效果如下:
解决方法:
- 给下面的元素position设置为absolute或者fixed(会影响后边元素)
- 下面的元素设置左浮动(会影响后边元素)
- 给下面的元素设置display:inline-block
- 给其中一个div外面包一个div,并给div设置问题1中的7中方法即可
- 尽量只给一个div设置margin
3、可以包含浮动元素——清除内部浮动
当两个子div都设置浮动后,父div不会将下面两个div包裹,但还是在父div的范围之内,
<body>
<div class="father">
<div class="child"></div>
<div class="child"></div>
</div>
</body>
.father {
border: 10px solid yellow;
}
.child {
float: left;
height: 200px;
width: 200px;
border: 10px solid tomato;
}
清除浮动:
给父div加上 overflow: hidden,触发父div的BFC属性,使下面的子div都处在父div的同一个BFC区域之内,此时已成功清除浮动。
还可以在浮动元素下加个<div style="clear:both"></div>(常用)
4、自适应两栏布局,阻止元素被浮动元素覆盖
<body>
<div class="aside"></div>
<div class="main"></div>
</body>
body {
width: 900px;
position: relative;
}
.aside {
width: 400px;
height: 150px;
float: left;
background: yellow;
}
.main {
height: 200px;
background: #fcc;
}
aside设置成float:left后,内容会与main部分重叠,通过产生一个新BFC即可实现如下效果。
.main {
overflow: hidden;
height: 200px;
background: #fcc;
}