🧨 大家好,我是 Smooth,一名大二的 SCAU 前端er
🏆 本篇文章将会用大白话的方式带你彻底掌握 BFC,从此面试不再惧怕 BFC 的提问!
🙌 如文章有误,恳请评论区指正,谢谢!
❤ 写作不易,「点赞」+「收藏」+「转发」 谢谢支持!
一、常见定位方案
在讲 BFC 之前,我们先来了解一下常见的定位方案,定位方案是控制元素的布局,有三种常见方案:
- 普通流 (normal flow)
在普通流中,元素按照其在 HTML 中的先后位置至上而下布局,在这个过程中,行内元素水平排列,直到当行被占满然后换行,块级元素则会被渲染为完整的一个新行,除非另外指定,否则所有元素默认都是普通流定位,也可以说,普通流中元素的位置由该元素在 HTML 文档中的位置决定。
而对于 float
的 不完全脱离文档流 和 position: absolute
的完全脱离文档流,指的就是上面这个 HTML 的普通流
-
float
对于浮动,是指元素先按照普通流的位置出现,然后将元素移动到所在行的最左边或最右边 -
absolute
在绝对定位布局中,元素会完全脱离普通流,而元素具体的位置是在相对于不为 static 的第一个父元素 及绝对定位的坐标决定。
二、BFC 概念
Formatting context(格式化上下文) 是 W3C CSS2.1 规范中的一个概念。它是页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用。
所以,BFC 是什么呢?
BFC 是块级格式化上下文,是一个独立的渲染区域,让处于 BFC 内部的元素与外部的元素相互隔离,使内外元素的定位不会相互影响。
通俗一点来讲,可以把 BFC 理解为一个封闭的大箱子,箱子内部的元素无论如何翻江倒海,都不会影响到外部。
三、BFC 规则
-
BFC 中子元素的 margin box 的左边, 与包含块 (BFC) border box的左边相接触 (子元素 absolute 除外)
-
BFC 的区域不会与 float 的元素区域重叠
-
BFC
就是一个块级元素,块级元素会在垂直方向一个接一个的排列 -
BFC
就是页面中的一个隔离的独立容器,容器里的标签不会影响到外部标签 -
垂直方向距离由
margin
决定,属于同一个BFC
的两个相邻标签外边距会发生重叠,属于不同BFC
的不会重叠 -
计算
BFC
的高度时,浮动元素也参与计算
四、触发 BFC 的条件
只要元素满足下面任一条件即可触发 BFC 特性:
- body 根元素就是一个 BFC
- 浮动元素:float 除 none 以外的值
- 绝对定位元素:position (absolute、fixed)
- display 为 inline-block、table-cell、flex
- overflow 除了 visible 以外的值 (hidden、auto、scroll)
相信大家在看 BFC 文章时经常会看到上面的字眼吧,没有案例不太好理解,下面便给出几个案例带你真正掌握 BFC
五、BFC 特性及应用
1. 阻止margin
重叠
对于同一个 BFC 内的两个相邻元素,如果分别设置了上下边距,那么会发生折叠(取大的那个)
<head>
div{
width: 50px;
height: 50px;
background: pink;
margin: 50px;
}
</head>
<body>
<div></div>
<div></div>
</body>
从效果上看,因为两个 div 元素都处于同一个 BFC 容器 (这里指 body 元素) ,所以第一个 div 的下边距和第二个 div 的上边距发生了重叠,所以两个盒子之间距离只有 50px(刚好一个正方形的高度),而不是 100px(两个正方形的高度)。
首先这不是 CSS 的 bug,我们可以理解为一种规范,如果想要避免外边距的重叠,可以将其放在不同的 BFC 容器中。
<div class="container">
<div class="child"></div>
</div>
<div class="container">
<div class="child"></div>
</div>
.container {
overflow: hidden;
}
.child {
width: 50px;
height: 50px;
background: pink;
margin: 50px;
}
这时候,两个盒子边距就变成了 100px
2. 清除浮动
我们都知道,浮动的元素会脱离普通文档流,来看下面一个例子
<style>
.container {
width: 500px;
border: 1px solid #000;
}
.child {
float: left;
width: 100px;
height: 100px;
background: pink;
}
</style>
<div class="container">
<div class="child"></div>
</div>
样例渲染异常的解释:由于容器内元素浮动,脱离了文档流,所以就只有外面容器的 2px 边距高度。
即方块没有如期将容器撑开
在这里问大家一个问题:我们在什么场景下会用到浮动呢?
毫无疑问,就是想用来布局定位的时候啊!
有了上面的这个回答,我们才知道为什么要清除浮动,因为我们只想使用浮动对页面进行我们所需的布局,但又不想他影响到上下文元素,即不影响页面的普通流,那么下面便讲讲这种方法如何实现吧。
方法
对于上面的例子,如果想内容在设置了浮动的条件下,还能撑开容器高度,那么可以通过触发容器的 BFC,那么容器将会包裹着浮动元素。
<style>
.container {
width: 500px;
border: 1px solid #000;
overflow: hidden;
}
.child {
float: left;
width: 100px;
height: 100px;
background: pink;
}
</style>
<div class="container">
<div class="child"></div>
</div>
效果如图:
3. BFC 可以阻止元素被浮动元素覆盖
先来看一个文字环绕效果:
<style>
.left {
height: 100px;
width: 100px;
float: left;
background: green;
}
.none {
width: 200px;
height: 200px;
background: grey;
}
</style>
<div class="left">左浮动元素</div>
<div class="none">
没设置浮动的元素,我的文字由于环绕没被覆盖,但实际方块被覆盖了
</div>
这时候其实第二个元素有部分被浮动元素所覆盖,(但是文本信息不会被浮动元素所覆盖) 如果想避免元素被覆盖,可以触发第二个元素的 BFC 特性,在第二个元素中加入 overflow: hidden,就会变成:
<style>
.left {
height: 100px;
width: 100px;
float: left;
background: green;
}
.none {
width: 200px;
height: 200px;
background: grey;
overflow: hidden;
}
</style>
<div class="left">左浮动元素</div>
<div class="none">
没设置浮动的元素,我的文字由于环绕没被覆盖,但实际方块被覆盖了
</div>
这个方法还可以用来实现两列自适应布局,效果不错,这时候左边的宽度固定,右边的内容自适应宽度(去掉上面右边内容的宽度即可)。
最后
我是 Smoothzjc,致力于产出更多且不仅限于前端方面的优质文章
写作不易,「点赞」+「收藏」+「转发」 谢谢支持❤
往期推荐
《都2022年了还不考虑来学React Hook吗?6k字带你从入门到吃透》
《一份不可多得的 Webpack 学习指南(1万字长文带你入门 Webpack 并掌握常用的进阶配置)》
《Github + hexo 实现自己的个人博客、配置主题(超详细)》
《React实战:使用Antd+EMOJIALL 实现emoji表情符号的输入》