【offer 收割机之 CSS 回顾系列】请你解释一下什么是 BFC ?他的应用场景有哪些?

本文最后更新于:2022年3月22日 晚上

🧨 大家好,我是 Smooth,一名大二的 SCAU 前端er
🏆 本篇文章将会用大白话的方式带你彻底掌握 BFC,从此面试不再惧怕 BFC 的提问!
🙌 如文章有误,恳请评论区指正,谢谢!

原文章链接

一、常见定位方案

在讲 BFC 之前,我们先来了解一下常见的定位方案,定位方案是控制元素的布局,有三种常见方案:

  1. 普通流 (normal flow)

在普通流中,元素按照其在 HTML 中的先后位置至上而下布局,在这个过程中,行内元素水平排列,直到当行被占满然后换行,块级元素则会被渲染为完整的一个新行,除非另外指定,否则所有元素默认都是普通流定位,也可以说,普通流中元素的位置由该元素在 HTML 文档中的位置决定。

而对于 float不完全脱离文档流position: absolute 的完全脱离文档流,指的就是上面这个 HTML 的普通流

  1. float 对于浮动,是指元素先按照普通流的位置出现,然后将元素移动到所在行的最左边或最右边

  2. 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 内的两个相邻元素,如果分别设置了上下边距,那么会发生折叠(取大的那个)

1
2
3
4
5
6
7
8
9
10
11
12
<head>
div{
width: 50px;
height: 50px;
background: pink;
margin: 50px;
}
</head>
<body>
<div></div>
<div></div>
</body>

image.png

从效果上看,因为两个 div 元素都处于同一个 BFC 容器 (这里指 body 元素) ,所以第一个 div 的下边距和第二个 div 的上边距发生了重叠,所以两个盒子之间距离只有 50px(刚好一个正方形的高度),而不是 100px(两个正方形的高度)。

首先这不是 CSS 的 bug,我们可以理解为一种规范,如果想要避免外边距的重叠,可以将其放在不同的 BFC 容器中。

1
2
3
4
5
6
<div class="container">
<div class="child"></div>
</div>
<div class="container">
<div class="child"></div>
</div>
1
2
3
4
5
6
7
8
9
10
.container {
overflow: hidden;
}

.child {
width: 50px;
height: 50px;
background: pink;
margin: 50px;
}

这时候,两个盒子边距就变成了 100px

image.png





2. 清除浮动

我们都知道,浮动的元素会脱离普通文档流,来看下面一个例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<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>

image.png

样例渲染异常的解释:由于容器内元素浮动,脱离了文档流,所以就只有外面容器的 2px 边距高度。

即方块没有如期将容器撑开


在这里问大家一个问题:我们在什么场景下会用到浮动呢?

毫无疑问,就是想用来布局定位的时候啊!

有了上面的这个回答,我们才知道为什么要清除浮动,因为我们只想使用浮动对页面进行我们所需的布局,但又不想他影响到上下文元素,即不影响页面的普通流,那么下面便讲讲这种方法如何实现吧。

方法

对于上面的例子,如果想内容在设置了浮动的条件下,还能撑开容器高度,那么可以通过触发容器的 BFC,那么容器将会包裹着浮动元素。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<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>

效果如图:

image.png





3. BFC 可以阻止元素被浮动元素覆盖

先来看一个文字环绕效果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<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>

image.png

这时候其实第二个元素有部分被浮动元素所覆盖,(但是文本信息不会被浮动元素所覆盖) 如果想避免元素被覆盖,可以触发第二个元素的 BFC 特性,在第二个元素中加入 overflow: hidden,就会变成:

image.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<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 实现自己的个人博客、配置主题(超详细)》

《10分钟让你彻底理解如何配置子域名来部署多个项目》

《一文理解配置伪静态解决 部署项目刷新页面404问题

《带你3分钟掌握常见的水平垂直居中面试题》

《React实战:使用Antd+EMOJIALL 实现emoji表情符号的输入》

《【建议收藏】长达万字的git常用指令总结!!!适合小白及在工作中想要对git基本指令有所了解的人群》

《浅谈javascript的原型和原型链(新手懵懂想学会原型链?看这篇文章就足够啦!!!)》https://juejin.cn/post/6993350461172482078)


作者:Smooth

文章链接:http://example.com/2022/03/16/%E3%80%90offer%20%E6%94%B6%E5%89%B2%E6%9C%BA%E4%B9%8B%20CSS%20%E5%9B%9E%E9%A1%BE%E7%B3%BB%E5%88%97%E3%80%91%E8%AF%B7%E4%BD%A0%E8%A7%A3%E9%87%8A%E4%B8%80%E4%B8%8B%E4%BB%80%E4%B9%88%E6%98%AF%20BFC%20%EF%BC%9F%E4%BB%96%E7%9A%84%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF%E6%9C%89%E5%93%AA%E4%BA%9B%EF%BC%9F/

版权说明:本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!