什么是BFC?
BFC全称block formatting context,块级格式化作用域,它的用途是形成一块独立的渲染区域,内部元素的渲染不会影响外界。
例:一个页面中<html>根元素就是一个BFC,网页中的弹窗则是另一个BFC,你关闭掉网页的弹窗不会影响页面的布局。
个人理解:有点类似于函数作用域中变量只在当前作用域能够使用。(不考虑闭包)
形成BFC的条件:
- 元素浮动 float:left或float:right
- 绝对/固定定位 position:absolute/fixed
- display属性设置为 inline-block、flex、inline-flex、grid等
- overflow值不为visible的块级元素
BFC的作用?
- 解决外边距重叠/内边距塌陷问题
- 清除浮动
- 阻止元素被父元素覆盖
外边距重叠:
<style>
.cube {
width: 100px;
height: 100px;
background: skyblue;
margin: 100px;
}
</style>
<body>
<!-- 理论上两个盒子相隔200px -->
<div class="cube"></div>
<div class="cube"></div>
</body>
实际执行后发现只有100px,这是因为CSS中两个元素的margin值不会叠加,而是取其中的一个最大值。
解决方案:把这两个块级元素分别放置在两个不同的BFC中就行
<style>
.cube {
width: 100px;
height: 100px;
background: skyblue;
margin: 100px;
}
.container {
overflow: hidden;
}
</style>
<body>
<div class="container"> // 每一个container容器就是一个BFC
<div class="cube"></div>
</div>
<div class="container">
<div class="cube"></div>
</div>
</body>
为什么这样做就能实现我们的目标呢?我个人的想法如下图所示:
container容器是没有设置宽高的,overflow:hidden触发了BFC,其内部的div元素的margin将它撑开,两个BFC之间是互不干扰的,两个div各自撑开容器100px,刚好实现了我们需要两个div相距200px的要求。
那父容器的container之间呢?很显然,两个父容器被包裹在同一个BFC里面,如果你给他们加上margin:100px,父容器之间间隔也只有100px
清除浮动:
我们先上代码:
<head>
<style>
.cube {
width: 100px;
height: 100px;
background: skyblue;
float: left;
}
.container {
border: 1px solid red;
}
</style>
</head>
<body>
<div class="container">
<div class="cube"></div>
</div>
</body>
执行后我们发现一个奇怪的现象:父元素的高度怎么没有了?!这是因为float浮动之后,原先的子元素脱离了文档流(normal flow),父元素自身是没设置高度的,所以父元素高度就坍塌了,只留下了2px的边框:
解决这个问题的方案同样是给它的父盒子container触发BFC。
<head>
<style>
.cube {
width: 100px;
height: 100px;
background: skyblue;
float: left;
}
.container {
border: 1px solid red;
overflow: hidden; // 触发BFC
}
</style>
</head>
<body>
<div class="container">
<div class="cube"></div>
</div>
</body>
阻止元素被父元素覆盖:
最后一个例子则是解决浮动后元素的重叠现象,这里同样先列出代码:
<head>
<style>
.floatDiv {
width: 100px;
height: 100px;
background-color: skyblue;
float: left;
}
.normalDiv {
width: 200px;
height: 200px;
background-color: pink;
}
</style>
</head>
<body>
<div class="floatDiv"></div>
<div class="normalDiv"></div>
</body>
其实这个问题和清除浮动时遇到的问题差不多, 蓝色元素浮动后脱离文档流,那么粉色元素就会和文档流的边缘对齐,导致了粉色占据了蓝色的位置(浮动)。
解决方案:可以给normalDiv添加overflow:hidden
<head>
<style>
.floatDiv {
width: 100px;
height: 100px;
background-color: skyblue;
float: left;
}
.normalDiv {
width: 200px;
height: 200px;
background-color: pink;
overflow: hidden;
}
</style>
</head>
<body>
<div class="floatDiv"></div>
<div class="normalDiv"></div>
</body>
至于为什么让normalDiv触发BFC,我个人的想法如下图:
也就是说,蓝盒子float浮动后,生成了新的BFC,脱离了文档流,但是粉色盒子还处在html内部的BFC中,所以粉色盒子会和html左边缘对齐,挤占蓝盒子的位置;只需要给粉色盒子触发BFC之后,两个盒子互不干扰,盒子内的元素撑开各自的盒子,所以重叠现象就消失了。
参考:
带你用最简单的方式理解最全面的BFC_哔哩哔哩_bilibili
到底什么是 BFC ?【CSS面试题】_哔哩哔哩_bilibili
html - Why can't I clear float when using BFC feature on body? - Stack Overflow
最后,这篇文章只是菜鸟的一点个人理解,如果理解有误,欢迎大家指出!