前言
在正题开始之前,想说两点:
-
对 BFC 的转变:知道 => 理解
在此之前的我,肯定知道 BFC 的存在,那么说说对 BFC 的理解?很难,无从下手。
此时的我,也许真能对 BFC 说道说道了。
-
支持王红元老师(coderwhy)
很多知识都是跟着王老师学习的,总能让我醍醐灌顶,YYDS。
正题
这是一篇观后总结笔记,看了B站 《coderwhy 官方账号》的对 BFC 知识点的视频讲解,所以下面的很多图片是来源于截图,见笑了。
FC
FC:formatting context,译为格式上下文,可以简单的理解为一种环境。
官方解释:
- 元素(块级元素,行内元素)只要在标准流中,就会属于一个 FC。
- 块级元素属于 BFC,行内元素属于 IFC。
- 但是不会存在一个元素既属于 BFC,又属于 IFC。
总结:FC 是一种环境,在该环境下就遵循该环境下的规则。
BFC
BFC: block formatting context,译为块级格式化上下文。
BFC 环境形成的条件
知道了 BFC 的存在,那么怎么才能看见它呢?
- 根元素(
<html>) - 浮动元素(
float值不为none) - 绝对定位元素(
position值为absolute或fixed) - 行内块元素(
display值为inline-block) - 表格单元格(
display值为table-cell,HTML 表格单元格默认值) - 表格标题(
display值为table-caption,HTML 表格标题默认值) - 匿名表格单元格元素(
display值为table、table-row、table-row-group、table-header-group、table-footer-group(分别是 HTML table、tr、tbody、thead、tfoot 的默认值)或inline-table) overflow值不为visible、clip的块元素display值为flow-root的元素contain值为layout、content或paint的元素- 弹性元素(
display值为flex或inline-flex元素的直接子元素),如果它们本身既不是 flex、grid 也不是 table 容器 - 网格元素(
display值为grid或inline-grid元素的直接子元素),如果它们本身既不是 flex、grid 也不是 table 容器 - 多列容器(
column-count或column-width(en-US) 值不为auto,包括column-count为1) column-span值为all的元素始终会创建一个新的 BFC,即使该元素没有包裹在一个多列容器中 (规范变更, Chrome bug)
只要满足了上面的条件,那么就会形成 BFC 环境(环境就是一种可知不可见的东西)。
BFC 环境下的规则
在理解规则之前,先来思考几个问题:
- 为什么块级盒子会一行一行的布局?
- 为什么盒子的布局是从浏览器的左边开始布局,而不是右边?
- 盒子之间的间距是通过 margin 来进行设置的,为什么?
我相信存在很多码友跟我一样的想法,这还用说,这不是约定俗成的嘛。是的,人是可以通过约定来形成规则,但是针对机器却是不行,它必须内部存在一种规则,根据该规则来执行对应的任务。
那么就来了,机器里面的规则(也可以说浏览器里面的规则)是什么?没有错,里面布局存在的规则就是 BFC规则 和 IFC规则。
官方解释:
- 规则一:在BFC中,盒子的布局是在垂直方向上一个一个的排列,从容器的顶部开始。
- 规则二:盒子与盒子之间的距离,通过
margin属性设置。 - 规则三:在同一个BFC环境中,两个垂直之间的盒子,都设置了 margin 属性,则会产生折叠(collapse)。
- 规则四:每个盒子的布局都是从容器的左边缘开始布局的。
这就是 BFC 环境中的规则,浏览器里面的规则就是基于 BFC 环境下的规则的(当然还有 IFC 环境下的规则)。
到了这里,相信大家或多或少对 BFC 有认知了吧。
BFC 代码演示
bfc.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>bfc</title>
<style>
* {
margin: 0;
padding: 0;
}
.box1 {
background-color: red;
width: 300px;
height: 100px;
}
.box2 {
background-color: blue;
width: 200px;
margin-top: 30px;
height: 100px;
}
</style>
</head>
<body>
<div class="box1"></div>
<div class="box2"></div>
</body>
</html>
效果图:
相信大家都知道效果如何,也相信大家都能解释了为什么是这种效果。
提示:这是 html 根标签已经形成了 BFC,那么就会遵守 BFC 规则。
BFC 的应用
- 解决 margin 折叠的问题。
- 解决清除浮动,高度塌陷的问题。
margin 折叠问题
BFC 环境的有个规则:就是在同一个 BFC 环境下,相邻的两个盒子,存在margin 会进行折叠,取最大值。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>bfc</title>
<style>
* {
margin: 0;
padding: 0;
}
.box1 {
background-color: red;
width: 300px;
height: 100px;
margin-bottom: 100px; /* margin-bottom */
}
.box2 {
background-color: blue;
width: 200px;
margin-top: 30px; /* margin-top */
height: 100px;
}
</style>
</head>
<body>
<div class="box1"></div>
<div class="box2"></div>
</body>
</html>
无论是 box1 盒子 还是 box2 盒子都在 html 根标签形成 BFC 中,所以会产生折叠。
那么想要不发生折叠,就让其中的一个盒子处于另外一个 BFC 环境中
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>bfc</title>
<style>
* {
margin: 0;
padding: 0;
}
.container {
overflow: auto; /* 形成 BFC 环境 */
}
.box1 {
background-color: red;
width: 300px;
height: 100px;
margin-bottom: 100px;
}
.box2 {
background-color: blue;
width: 200px;
margin-top: 30px;
height: 100px;
}
</style>
</head>
<body>
<div class="container">
<div class="box1"></div>
</div>
<div class="box2"></div>
</body>
</html>
这样就不会产生折叠,因为没有处于同一个 BFC 环境中。
清除浮动的问题
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>bfc</title>
<style>
* {
margin: 0;
padding: 0;
}
.container {
/* overflow: auto; */
}
.item {
background-color: red;
height: 50px;
width: 100px;
float: left; /* 浮动 */
}
</style>
</head>
<body>
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
</body>
</html>
在浮动布局的时候,就会产生一种现象,盒子内部设置了浮动,盒子的高度就塌陷了。那么解决方案就两种:
- 清除浮动
- 形成 BFC 环境
主要说下第二种解决方案。
先来关注一下,为什么设置了浮动,高度就塌陷了?是因为浮动元素,就已经脱离标准流了,不会把自身的高度汇报给父元素,从而父元素就没有高度了。
那么形成了 BFC 环境之后,就能把脱标元素的高度汇报给父元素了,这种说法对不对?答案是不对的。
因为脱标元素不仅仅只有浮动,还有绝对定位,那么把子元素设置为 position: absolute,并且再把父元素形成 BFC环境 之后,观察现象,也是没有汇报高度给父元素的,所以上面的那种说法是不成立的。
那么正确的结论是怎么样的呢?
官方解释:
这张截图挺模糊的,但是大致的意思就是:
针对 height:auto 的 BFC 环境的盒子,高度的计算如下:
- 如果子元素是行内元素,那么高度就是行高的顶部到行高的底部距离。
- 如果子元素是块级元素,那么高度就是最上面盒子的上边缘到最下面盒子的下边缘的距离。
- 如果是绝对定位元素,那么将直接被忽略。
- 如果是浮动元素,那么就会增加高度,完全包裹子元素的下边缘。
这也就解释了上面的那种说法是错误的。因为 BFC 盒子,发现子元素是浮动元素,就增加自身的高度,来完全包裹子元素,并不是子元素汇报高度给父元素。
上面满足的条件:
- 形成 BFC。
- height 为 auto。
总结
虽然是看了 coderwhy 视频来写的笔记,但是还是避免不了错误,所以说有误的话,请说出来,学习学习。
总的来说,对 BFC 的认识,我已经上升了一个台阶,你们呢?