【内推字节】欢迎简历chengxinsong@bytedance.com

浅析前端中的常说的BFC

一、前言

只知道BFC是块级格式上下文(block fomatting context),对于BFC的概念以及应用场景一直都不是很明白,今天着重去了解了一下,做了以下总结。


二、BFC的定义

解释BFC之前,首先介绍Box,Formatting Context的概念


2.1、Box: CSS布局的基本单位

Box 是 CSS 布局的对象和基本单位, 直观点来说,就是一个页面是由很多个 Box 组成的。元素的类型和 display 属性,决定了这个 Box 的类型。 不同类型的 Box, 会参与不同的 Formatting Context(一个决定如何渲染文档的容器),因此Box内的元素会以不同的方式渲染。让我们看看有哪些盒子: 

1、block-level box:display 属性为 block, list-item, table 的元素,会生成 block-level box。并且参与 block fomatting context;

2、inline-level box:display 属性为 inline, inline-block, inline-table 的元素,会生成 inline-level box。并且参与 inline formatting context;

3、run-in box: css3 中才出现


2.2、Formatting context

 Formatting context 是 W3C CSS2.1 规范中的一个概念。它是页面中的一块渲染区域,并且有一套渲染规则,

它决定了其子元素将如何定位,以及和其他元素的关系和相互作用。

最常见的 Formatting context 有 Block fomatting context (简称BFC)和 Inline formatting context (简称IFC)。 CSS2.1 中只有 BFC 和 IFC, CSS3 中还增加了 GFC 和 FFC。


2.3、BFC

 BFC(Block Formatting Context)直译为“块级格式化范围”。是 W3C CSS 2.1 规范中的一个概念,它决定了元素如何对其内容进行定位,以及与其他元素的关系和相互作用 当涉及到可视化布局的时候,Block Formatting Context提供了一个环境,HTML元素在这个环境中按照一定规则进行布局。一个环境中的元素不会影响到其它环境中的布局。比如浮动元素会形成BFC,浮动元素内部子元素的主要受该浮动元素影响,两个浮动元素之间是互不影响的。这里有点类似一个BFC就是一个独立的行政单位的意思。 也可以说BFC就是一个作用范围。可以把它理解成是一个独立的容器,并且这个容器的里box的布局,与这个容器外的毫不相干


三、怎样才能形成BFC
1、float的值不能为none
2、overflow的值不能为visible
3、display的值为table-cell, table-caption的任何一个
4、position的值不为relative和static 


四、BFC的约束规则

1、内部的Box会在垂直方向上一个接一个的放置

2、垂直方向的距离有margin决定(属于同一个BFC的两个相邻Box的margin会发生重叠,与方向无关)

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

4、BFC的区域不会与float的元素区域重叠

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

6、BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面元素,反之亦然


看到以上的几条约束,让我想起学习css时的几条规则

1、Block元素会扩展到与父元素同宽,所以block元素会垂直排列 

2、垂直方向上的两个相邻DIV的margin会重叠,而水平方向不会(此规则并不完全正确) 

3、浮动元素会尽量接近往左上方(或右上方) 

4、父元素设置overflow:hidden或浮动父元素,则会包含浮动元素


五、BFC的作用

5.1不和浮动元素重叠

如果一个浮动元素后面跟着一个非浮动的元素,那么就会产生一个覆盖的现象,很多自适应的两栏布局就是这么做的。


<html>
    <head>
        <title>bfc</title>
    </head>
    <style>
        body {
            width: 300px;
        }
    
        .aside {
            width: 100px;
            height: 150px;
            float: left;
            background: #5579ee;
        }
    
        .main {
            height: 200px;
            background: #cccccc;
        }
    </style>
    <body>
        <div class="aside"></div>
        <div class="main"></div>
    </body>
</html>

分析:

很明显,.aside和.mian重叠了。试分析一下,由于两个box都处在同一个BFC中,都是以BFC边界为起点,如果两个box本身都具备BFC的话,会按顺序一个一个排列布局,现在.main并不具备BFC,根据BFC布局规则第3条

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

虽然存在浮动的元素aside,但main的左边依然会与包含块的左边相接触 根据BFC布局规则第四条

BFC的区域不会与float box重叠

我们可以通过通过触发main生成BFC, 来实现自适应两栏布局

.main {
    overflow: hidden;
}

当触发main生成BFC后,这个新的BFC不会与浮动的aside重叠。因此会根据包含块的宽度,和aside的宽度,自动变窄。

效果如下:



5.2清除元素浮动


看到这个图应该就知道什么叫清除浮动?

<html>
    <head>
        <title>bfc</title>
    </head>
    <style>
        body {
            width: 300px;
        }
    
        .box {
            width: 300px;
            border: 5px solid #5579ee;
        }
    
        .child {
            width: 100px;
            height: 100px;
            border: 5px solid #cccccc;
            float: left;
        }
    </style>
    <body>
        <!-- 清除元素内部浮动 -->
        <div class="box">
            <div class="child"></div>
            <div class="child"></div>    
        </div>
    </body>
</html>

根据BFC布局规则第五条:

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

为了达到清除内部浮动,我们可以触发box生成BFC,在box计算高度的时候,box内部的浮动元素child也会参与计算。

.box{
  overflow:hidden
}

加上之后



5.3防止垂直margin重叠


这个就是两个元素之间的margin重叠了。为什么会重叠呢?

<html>
    <head>
        <title>bfc</title>
    </head>
    <style>
        body {
            width: 300px;
        }
    
       p{
           width: 300px;
           color: #5579ee;
           background: #cccccc;
           line-height: 100px;
           text-align: center;
           margin: 100px;
       }
    </style>
    <body>
        <!-- 防止垂直margin重叠 -->
        <p>saucxs</p>
        <p>songEagle</p>
    </body>
</html>

分析:

可以看出来,这两个p之间的距离是100px;反生了margin重叠。根据BFC布局规则的第二条

垂直方向的距离有margin决定(属于同一个BFC的两个相邻Box的margin会发生重叠,与方向无关)

我们可以在p的外边包一层容器,并处罚该容器生成一个BFC。那么这两个P就不不属于同一个BFC,就不会发生margin重叠。


<html>
    <head>
        <title>bfc</title>
    </head>
    <style>
        body {
            width: 1000px;
        }
        
        .wrap{
            overflow: hidden;
        }
    
       p{
           width: 300px;
           color: #5579ee;
           background: #cccccc;
           line-height: 100px;
           text-align: center;
           margin: 100px;
       }
    </style>
    <body>
        <!-- 防止垂直margin重叠 -->
        <div class="wrap">
            <p>saucxs</p>
        </div>
        <p>songEagle</p>
    </body>
</html>

按照BFC 的定义,只有属于同一个BFC时候,两个元素才会发生垂直的margin重叠,这个包括相邻元素,嵌套元素,只要他们之间没有阻挡(边框,非空内容,padding等)就会发生margin重叠。因此解决这个margin的重叠问题,只要让他们不在同一个BFC就行,但是对于相邻元素来说意义不大,没有必要给他们加个外坑,但是对于嵌套元素来说还是很有必要的,只要把父级元素设置为BFC,这样子元素的margin就不会和父元素的margin重叠。

文章转载:原创
感谢你的阅读,本文由 sau交流学习社区 版权所有。
如若转载,请注明出处:sau交流学习社区-power by saucxs(程新松)(/page/537.html)
交流咨询
    官方QQ群
    群号663940201,欢迎加入!
    sau交流学习社区交流群

微信群
欢迎加入微信群
微信公众号
欢迎关注微信公众号

图文推荐

微信群
saucxs聊天机器人
saucxs
hi ,欢迎来到sau交流学习社区,欢迎与我聊天,问我问题哦!
您正在使用的浏览器是,不在支持范围内!
为了您的正常使用与展示,推荐使用Chrome浏览器68以上版本
支持浏览器:
火狐浏览器最新版
Safari浏览器最新版
Edge浏览器最新版
IE浏览器10,11