理解BFC
理解BFC(块级格式化上下文)之前,先看一下FC(格式化上下文)是什么意思:
格式化上下文是决定盒子之间如何布局的环境,不同的格式化上下文如何布局盒子由自身的规则来决定。正常文档流下,盒模型归属到格式化上下文。块级盒子参加块级格式化上下文
BFC块格式化上下文 是块盒子的布局过程发生的区域,也是浮动元素与其他元素交互的区域。因此BFC是一块独立渲染区域,内部元素的渲染不会影响边界以外的元素。
BFC规则
内部盒子会在垂直方向排列
在同一个BFC中,垂直方向上,相邻两个盒子的margin会重叠,值取两者中较大的
BFC就是页面上的一个隔离的独立容器,里外互相不受影响
计算BFC元素的高度时,考虑BFC所包含的所有子元素,连浮动元素也要参与计算。
当元素不是BFC的子元素时,浮动元素高度不参与BFC计算(常见的盒子塌陷问题)
在一个BFC中,每个元素的左边缘都会紧贴着包含块的左边缘
BFC的区域不会与float box重叠。
BFC触发条件
- 根元素html
- 浮动元素(float不为none的元素)
- 绝对定位元素(position为absolute或fixed)
- overflow不为visible或clip的块级元素
- 行内块元素(display为inline-block), 表格单元格(display为table-cell)
- display值为table-caption, flex, inline-flex
- display 值为 flow-root 的元素
使用 overflow: auto; 触发 BFC 的方法缺点在于不够直观,其次可能产生不必要的滚动条或剪切阴影等副作用。
因此mdn指出,使用 display: flow-root (或 display: flow-root list-item)将创建一个新的 BFC,而不会产生任何其他潜在的问题副作用。flow-root 关键字的意义是,创建的内容本质上类似于一个新的根元素(如 所做),并确定这个新的上下文如何创建及其流布局如何实现。
所以总结一句话,为一个元素创建BFC,可以包含内部浮动。排除外部浮动,阻止外边距重叠。
BFC应用1: 解决margin重叠
xml
<head>
<meta charset="UTF-8">
<style>
.box1 {
width: 100px;
height: 100px;
background-color: green;
margin-bottom: 30px;
}
.box2 {
width: 200px;
height: 100px;
background-color: green;
margin-top: 50px;
}
</style>
</head>
<body>
<div class="box1">盒子1</div>
<div class="box2">盒子2</div>
</body>
如下图所示,box1和box1此时同处于html的BFC中,并且box1和box2在垂直方向上相邻,所以会出现margin重叠,取两者其中较大的值50px
那么如何解决呢?错误做法是直接给box1添加一个BFC,此时box1确实是已经形成了BFC(可以理解成box1内部形成了BFC),但是对于box1这个元素的本身,还是和box2同属于html的BFC中,所以还是会发生margin重叠
正确做法:要给box1套一层,然后给box1外层的盒子设置BFC
xml
<head>
<meta charset="UTF-8">
<style>
.box1 {
width: 100px;
height: 100px;
background-color: green;
margin-bottom: 30px;
}
.box2 {
width: 200px;
height: 100px;
background-color: green;
margin-top: 50px;
}
.container {
overflow: hidden;
}
</style>
</head>
<body>
<div class="container">
<div class="box1">盒子1</div>
</div>
<div class="box2">盒子2</div>
</body>
此时成功解决上下margin塌陷问题
BFC应用2:解决浮动高度塌陷问题
考虑如下场景
当给container里面的box设置浮动的时候,该div元素会脱离文档流,此时container不会有高度。
xml
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.container {
background-color: yellowgreen;
border: 2px solid black;
}
.box {
border: 1px solid black;
width: 100px;
height: 100px;
float: left;
}
</style>
</head>
<body>
<div class="container">
<div class="box">盒子1</div>
</div>
</body>
当元素不是BFC的子元素时,浮动元素高度不参与BFC计算(常见的盒子塌陷问题)
BFC能解决浮动元素塌陷问题的原因在于:计算BFC元素的高度时,考虑BFC所包含的所有子元素,连浮动元素也要参与计算。所以为container元素添加overflow属性来设置BFC,此时container是一个新的BFC,计算高度时会包含浮动的子元素,因此解决浮动塌陷问题。
xml
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.container {
background-color: yellowgreen;
border: 2px solid black;
overflow: hidden;
}
.box {
border: 1px solid black;
width: 100px;
height: 100px;
float: left;
}
</style>
</head>
<body>
<div class="container">
<div class="box">盒子1</div>
</div>
</body>
BFC应用3:自适应两栏布局
每个元素的左外边距与包含块的左边界相接触。即使元素浮动,也会同样。
xml
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
.left {
width: 100px;
height: 150px;
float: left;
background: gray;
}
.right {
height: 300px;
background: rgb(170, 54, 236);
background: yellowgreen;
}
</style>
</head>
<body>
<div class="left">LEFT</div>
<div class="right">RIGHT</div>
</body>
创建一个新的BFC会排除外部浮动,因此为right创建BFC可以实现自适应两栏布局。为right元素添加overflow:hidden来创建一个新的BFC
css
.right {
height: 300px;
background: rgb(170, 54, 236);
background: yellowgreen;
overflow: hidden;
}
参考: