前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android开发人员一次搞懂前端BFC原理

Android开发人员一次搞懂前端BFC原理

作者头像
用户2802329
发布2018-08-07 17:47:45
6760
发布2018-08-07 17:47:45
举报
文章被收录于专栏:Android先生Android先生
什么是BFC

BFC全称是Block Formatting Context,即块格式化上下文。它是CSS2.1规范定义的,关于CSS渲染定位的一个概念。

在介绍清楚BFC之前,我们先简单回顾一下CSS中的盒模型:盒模型包括内容(Content)、Padding、边框(Border)和Margin 。

而块级格式化上下文(BFC)是页面中一个相对独立的模块,它定义了它内部的块级盒子(块级元素的盒子模型)如何排布和布局。html的根元素<html></html>标签就会产生一个BFC区域。

BFC规则

1、内部的块级盒子会在垂直方向,一个接一个地放置。

2、块级盒子垂直方向的距离由margin决定。属于同一个BFC的两个相邻块级盒子的margin会发生重叠。

3、每个元素的margin box的左边,与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。

4、BFC的区域不会与float box重叠。

5、BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。

6、计算BFC的高度时,浮动元素也参与计算。

创建新的BFC

根元素或其它包含它的元素;

浮动(元素的float不为none);

绝对定位元素(元素的position为absolute或fixed);

行内块inline-blocks(元素的display: inline-block);

表格单元格(元素的display: table-cell,HTML表格单元格默认属性);

overflow的值不为visible的元素;

弹性盒 flex boxes(元素的display: flex或inline-flex);

BFC的区域

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为div1div2div3都属于div0所创建的BFC区域下。

又因为id=div3的div又创建了一个BFC区域,所以div5div6就不再属于div0所创建的BFC区域内,而属于div3创建的BFC区域内。

知道了BFC的区域的划分,我们通过每一个实例,来对BFC的规则做一个演示和体会

BFC代码实例

1、内部的块级盒子会在垂直方向,一个接一个地放置。
 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的规则。

2、块级盒子垂直方向的距离由margin决定。属于同一个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    </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值。如下图展示:

如何解决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值不会发生重叠。

3、每个元素的margin box的左边,与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
4、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            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由于漂浮脱离了文档流,导致的。

5、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
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的影响。

6、计算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        .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

声明:本文是丨大麦原创,已获其授权原创发布

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-08-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Android先生 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • BFC规则
  • 创建新的BFC
  • BFC的区域
  • BFC代码实例
    • 1、内部的块级盒子会在垂直方向,一个接一个地放置。
      • 2、块级盒子垂直方向的距离由margin决定。属于同一个BFC的两个相邻块级盒子的margin会发生重叠。
        • 如何解决margin边距重叠
      • 3、每个元素的margin box的左边,与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
        • 4、BFC的区域不会与float box重叠。
          • 5、BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素,反之也如此。
            • 6、计算BFC的高度时,浮动元素也参与计算。
            • 复盘
            相关产品与服务
            容器服务
            腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档