BFC全称是Block Formatting Context,即块格式化上下文。它是CSS2.1规范定义的,关于CSS渲染定位的一个概念。
在介绍清楚BFC之前,我们先简单回顾一下CSS中的盒模型:盒模型包括内容(Content)、Padding、边框(Border)和Margin 。
而块级格式化上下文(BFC)是页面中一个相对独立的模块,它定义了它内部的块级盒子(块级元素的盒子模型)如何排布和布局。html的根元素<html></html>
标签就会产生一个BFC区域。
1、内部的块级盒子会在垂直方向,一个接一个地放置。
2、块级盒子垂直方向的距离由margin决定。属于同一个BFC的两个相邻块级盒子的margin会发生重叠。
3、每个元素的margin box的左边,与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
4、BFC的区域不会与float box重叠。
5、BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
6、计算BFC的高度时,浮动元素也参与计算。
根元素或其它包含它的元素;
浮动(元素的float不为none);
绝对定位元素(元素的position为absolute或fixed);
行内块inline-blocks(元素的display: inline-block);
表格单元格(元素的display: table-cell,HTML表格单元格默认属性);
overflow的值不为visible的元素;
弹性盒 flex boxes(元素的display: flex或inline-flex);
1<div id="div0" class="main BFC">
2 <div id="div1" class="div1 margin-100px">元素1</div>
3 <div id="div2" class="div2 margin-100px">元素2</div>
4 <div id="div3"class="div3 margin-100px BFC">
5 <div id="div5" class="child">子元素1</div>
6 <div id="div6" class="child">子元素2</div>
7 </div>
8</div>
BFC区域包含创建BFC元素的所有子元素,但不包括又创建BFC元素下面的所有子元素。
看上面这段代码,id=div0
的元素创建了一个BFC区域,该元素下面的id为div1
、div2
、div3
都属于div0
所创建的BFC区域下。
又因为id=div3
的div又创建了一个BFC区域,所以div5
和div6
就不再属于div0
所创建的BFC区域内,而属于div3
创建的BFC区域内。
知道了BFC的区域的划分,我们通过每一个实例,来对BFC的规则做一个演示和体会
1<!DOCTYPE html>
2<html lang="en">
3<head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <meta http-equiv="X-UA-Compatible" content="ie=edge">
7 <title>Document</title>
8 <script>
9
10 </script>
11 <style>
12 .main{
13 margin: 10px;
14 border: 3px solid red;
15 }
16 .div1{
17 opacity: 0.5;
18 background: greenyellow;
19 width: 100px;
20 height: 100px;
21
22 }
23 .div2{
24 opacity: 0.5;
25 background: rebeccapurple;
26 width: 100px;
27 height: 100px;
28 }
29 .BFC{
30 display: inline-block;
31 }
32 </style>
33</head>
34<body>
35 <div id="div0" class="main BFC">
36 <div id="div1" class="div1">元素1</div>
37 <div id="div2" class="div2">元素2</div>
38 </div>
39</body>
40</html>
结果:
我们看到我们给div0
设置了一个BFC的css样式:display:inline-block
,此时我们给div0
创建了一个BFC。而它内部的div元素都带有默认的css属性:display:block
,因此它们会生成块级盒子,在BFC区域内垂直排布。这就是我们大家都知道的常规流。
其实我们会发现我们当初学习HTML和CSS时,很多块级元素的规则其实就是BFC的规则。
1<!DOCTYPE html>
2<html lang="en">
3<head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <meta http-equiv="X-UA-Compatible" content="ie=edge">
7 <title>Document</title>
8 <script>
9
10 </script>
11 <style>
12 .main{
13 margin: 10px;
14 border: 3px solid red;
15 }
16 .div1{
17 opacity: 0.5;
18 background: greenyellow;
19 width: 100px;
20 height: 100px;
21 }
22 .div2{
23 opacity: 0.5;
24 background: rebeccapurple;
25 width: 100px;
26 height: 100px;
27 }
28 .BFC{
29 display: inline-block;
30 }
31 .margin-100px{
32 margin: 100px;
33 }
34 </style>
35</head>
36<body>
37 <div id="div0" class="main BFC">
38 <div id="div1" class="div1 margin-100px">元素1</div>
39 <div id="div2" class="div2 margin-100px">元素2</div>
40 </div>
41</body>
42</html>
结果:
这就是BFC中经常发生的边距重叠的情况。而且重叠的情况会根据重叠的块级盒子的margin值有关,在这里即:div1的margin-bottom和div2的margin-top值有关系。
分三种情况:
当div1的margin-bottom和div2的margin-top值都为正数,则重叠时,取最大的值展示。
当div1的margin-bottom和div2的margin-top值一正一负时,则重叠时,取他们之间的差值展示。如下图展示:
当div的margin-bottom和div2的margin-top值都为负数,则重叠时,取他们绝对值最大的margin值。如下图展示:
根据BFC规则:属于同一个BFC的两个相邻块级盒子的margin会发生重叠。因此我们只要使div1与div2不属于同一个BFC即可:
1<!DOCTYPE html>
2<html lang="en">
3<head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <meta http-equiv="X-UA-Compatible" content="ie=edge">
7 <title>Document</title>
8 <script>
9
10 </script>
11 <style>
12 .main{
13 margin: 10px;
14 border: 3px solid red;
15 }
16 .div1{
17 opacity: 0.5;
18 background: greenyellow;
19 width: 100px;
20 height: 100px;
21 }
22 .div2{
23 opacity: 0.5;
24 background: rebeccapurple;
25 width: 100px;
26 height: 100px;
27 }
28 .BFC{
29 display: inline-block;
30 }
31 .margin-100px{
32 margin: 100px;
33 }
34
35
36 </style>
37</head>
38<body>
39 <div id="div0" class="main BFC">
40 <div id="div1" class="div1 margin-100px">元素1</div>
41 <div class="BFC">
42 <div id="div2" class="div2 margin-100px">元素2</div>
43 </div>
44 </div>
45</body>
46</html>
此时我们将div2包裹在一个新的div下面,通过给这个新的div设置display:inline-block
新创建了一个BFC,因此此时的div1和div2不在一个BFC区域中,所以他们的margin值不会发生重叠。
1<!DOCTYPE html>
2<html lang="en">
3<head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <meta http-equiv="X-UA-Compatible" content="ie=edge">
7 <title>Document</title>
8 <script>
9
10 </script>
11 <style>
12 .main{
13 margin: 10px;
14 border: 3px solid red;
15 }
16 .div1{
17 opacity: 0.5;
18 background: greenyellow;
19 width: 100px;
20 height: 100px;
21 }
22 .div2{
23 opacity: 0.5;
24 background: rebeccapurple;
25 width: 100px;
26 height: 100px;
27 }
28 .BFC{
29 display: inline-block;
30 }
31 .margin-100px{
32 margin: 100px;
33 }
34 .float-left{
35 float: left;
36 }
37
38
39 </style>
40</head>
41<body>
42 <div id="div0" class="main BFC">
43 <div id="div1" class="div1 margin-100px float-left">元素1</div>
44 <div id="div2" class="div2 margin-100px">元素2</div>
45 </div>
46</body>
47</html>
这里我们仔细想想为什么会发生这样的情况:
1、首先我们的div1和div2处于同一个BFC区域中,我们这里暂且把这个BFC称作BFC0;
2、我们给div1设置了float:left
;
3、由于div1进行了漂浮,而div2与div1处于BFC0中,所以div2和div1还是会发生重叠;
要解决漂浮重叠,我们也可以通过BFC进行解决,我们依旧给div2放到一个新的BFC区域中,那么根据BFC的规则,BFC的区域不会与float box重叠,就可以解决。
1<!DOCTYPE html>
2<html lang="en">
3<head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <meta http-equiv="X-UA-Compatible" content="ie=edge">
7 <title>Document</title>
8 <script>
9
10 </script>
11 <style>
12 .main{
13 margin: 10px;
14 border: 3px solid red;
15 }
16 .div1{
17 opacity: 0.5;
18 background: greenyellow;
19 width: 100px;
20 height: 100px;
21 }
22 .div2{
23 opacity: 0.5;
24 background: rebeccapurple;
25 width: 100px;
26 height: 100px;
27 }
28 .BFC{
29 overflow: auto;
30 }
31 .margin-100px{
32 margin: 100px;
33 }
34 .float-left{
35 float: left;
36 }
37 </style>
38</head>
39<body>
40 <div id="div0" class="main BFC">
41 <div id="div1" class="div1 margin-100px float-left">元素1</div>
42 <div class="BFC">
43 <div id="div2" class="div2 margin-100px">元素2</div>
44 </div>
45 </div>
46</body>
47</html>
结果:
此时我们通过给div2新建了一个BFC区域,因此它没有与div1漂浮发生重叠。
这时候仔细的小伙伴可能会问,根据BFC的规则1,为什么div2没有垂直方向独占一行?
这是因为div1发生了漂浮,它会影响它后面的一个元素,因此并不是div2没有在垂直方向独占一行,而是因为div1漂浮的缘故,div2和div1一起占了一行,而又因为新建了一个BFC,因此div2没有和div1重叠在一起,所以此时看起来他们并没有垂直排布。其实是div2独占了一行,而由于div1由于漂浮脱离了文档流,导致的。
1<!DOCTYPE html>
2<html lang="en">
3<head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <meta http-equiv="X-UA-Compatible" content="ie=edge">
7 <title>Document</title>
8 <script>
9
10 </script>
11 <style>
12 .main{
13 margin: 10px;
14 border: 3px solid red;
15 }
16 .div1{
17 opacity: 0.5;
18 background: greenyellow;
19 width: 100px;
20 height: 100px;
21 }
22 .div2{
23 opacity: 0.5;
24 background: rebeccapurple;
25 width: 100px;
26 height: 100px;
27 }
28
29 .child{
30 width: 50px;
31 height: 50px;
32 background: orange;
33 margin: 10px;
34 }
35 .BFC{
36 display: inline-block;
37 }
38 .margin-100px{
39 margin: 100px;
40 }
41 .float-left{
42 float: left;
43 }
44 </style>
45</head>
46<body>
47 <div id="div0" class="main BFC">
48 <div id="div1" class="div1 float-left">元素1</div>
49 <div id="div2" class="div2">
50 元素2
51 <div class="child"></div>
52 <div class="child"></div>
53 <div class="child"></div>
54 </div>
55
56 </div>
57</body>
58</html>
结果:
我们可以看到由于div1进行漂浮,div2中的文字和设置了child
样式的div被受到了div1漂浮的影响。
我们给div2创建新的BFC区域,即可解决问题。
此时,div2不再受到div1的影响。
当我们使用漂浮的时候,我们经常会遇到高度塌陷的问题。例如:
1<!DOCTYPE html>
2<html lang="en">
3<head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <meta http-equiv="X-UA-Compatible" content="ie=edge">
7 <title>Document</title>
8 <script>
9
10 </script>
11 <style>
12 .main{
13 margin: 10px;
14 border: 3px solid red;
15 }
16 .div1{
17 opacity: 0.5;
18 background: greenyellow;
19 width: 100px;
20 height: 100px;
21 }
22 .BFC{
23 display: inline-block;
24 }
25 .float-left{
26 float: left;
27 }
28
29 </style>
30</head>
31<body>
32 <div id="div0" class="main">
33 <div class="div1 float-left">元素1</div>
34 </div>
35</body>
36</html>
结果:
我们可以看到此时我们没有给div0设置BFC,同时使div1进行漂浮,我们看到div0计算高度的时候没有包含div1的高度。这就是我们所说的高度塌陷的情况。
我们也可以用BFC进行解决这个问题,我们给div0创建一个BFC,此时它在计算高度时,会同时包括div1的高度。
BFC其实就是CSS范畴的知识,它对块级元素生成的块级盒子进行了一些规则的限制,使这些块级盒子按照规则在html文档中排布和布局。或许你之前并没有系统的学习过BFC这个知识点,但你一定是通过经验之谈,对BFC多多少少是有了解的。
作者:丨大麦
地址:https://juejin.im/post/5b6065abf265da0fa00a2ec4
声明:本文是丨大麦原创,已获其授权原创发布