一文带你彻底弄懂BFC(块级格式上下文)

先说说FC,FC的含义就是Fomatting Context。它是CSS2.1规范中的一个概念。它是页面中的一块渲染
区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用。BFC和IFC
都是常见的FC。分别叫做Block Fomatting Context 和Inline Formatting Context。

BFC(Block Formatting Context)叫做“块级格式化上下文”。

BFC的布局规则

1.内部的盒子会在垂直方向,一个个地放置;

2.盒子垂直方向的距离由margin决定,属于同一个BFC的两个相邻Box的上下margin会发生重叠。垂直方向上的距离会叠加,值由最大margin值决定(如果不要叠加,就需要将该盒子变成一个独立的盒子)

3.每个元素的左边,与包含的盒子的左边相接触,即使存在浮动也是如此;

4.BFC的区域不会与float重叠;

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

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

形成BFC的条件

  • 根元素(即body);
  • 浮动元素,float的属性不为none;
  • 定位元素,position为absolute或fixed;
  • display为inline-block,table-cell,table-caption,flex;
  • overflow不为visible。(值为hidden/auto/scroll时)

BFC的作用

  • 解决margin重叠的问题(添加独立BFC)
  • 解决浮动高度塌陷的问题(在父级添加overflow:hidden)
  • 解决侵占浮动元素的问题(添加overflow:hidden清除浮动)

BFC特性详解

接下来我将用例子一一对其特性进行说明。

特性一

内部的盒子会在垂直方向,一个个地放置。

这个很好理解,body本身就是一个BFC,根据块级元素的定义,块级元素是会占满一整行的。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>BFC</title>
    <style>
        .container {
            width: 300px;
            border: 1px solid #000;

            /*触发BFC*/
            overflow: hidden;
            height: 400px;
        }

        .box1 {
            height: 20px;
            width: 50%;
            background-color: blue;
        }

        .box2 {
            height: 20px;
            width: 50%;
            background-color: yellow;
        }

    </style>
</head>
<body>
<div class="container">
    <div class="box1"></div>
    <div class="box2"></div>


</div>
</body>
</html>

img






特性二

盒子垂直方向的距离由margin决定,属于同一个BFC的两个相邻Box的上下margin会发生重叠。垂直方向上的距离会叠加,值由最大margin值决定(如果不要叠加,就需要将该盒子变成一个独立的盒子)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>BFC</title>
    <style>
        .container {
            width: 300px;
            border: 1px solid #000;

            /*触发BFC*/
            overflow: hidden;
            height: 400px;
        }

        .box1{
            height: 20px;
            margin: 50px 0;
            background-color: blue;
        }

        .box2{
            height: 20px;
            margin: 60px 0;
            background-color: yellow;
        }

    </style>
</head>
<body>
<div class="container">
    <div class="box1"></div>
    <div class="box2"></div>
</div>
</body>
</html>

img

如果希望这两个盒子之间的margin不要重叠,则需要使其中一个盒子形成一个独立容器,即触发BFC。

这也是利用了BFC的第五个特性。

  • BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素,反之也如此。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>BFC</title>
    <style>
        .container {
            width: 300px;
            border: 1px solid #000;

            /*触发BFC*/
            overflow: hidden;
            height: 400px;
        }

        .wrapper {
            width: 100%;
            overflow: hidden;
            border: 2px solid purple;
        }

        .box1 {
            height: 20px;
            margin: 50px 0;
            background-color: blue;

        }

        .box2 {
            height: 20px;
            margin: 60px 0;
            background-color: yellow;
        }

    </style>
</head>
<body>
<div class="container">
    <div class="box1"></div>
    <div class="wrapper">
        <div class="box2"></div>
    </div>


</div>
</body>
</html>

img










特性三

3、每个元素的左边,与包含的盒子的左边相接触,即使存在浮动也是如此;

第三点也很好理解,就拿body来说,文档流都是从左往右排版的。即使存在浮动元素,BFC中其他元素的margin box的左边也会与包含块border box的左边相接触 。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .box {
            background: gray;
        }

        .left {
            /* 即使存在浮动元素,BFC中其他元素的margin box的左边也会与包含块border box的左边相接触 */
            /* 在这个例子中,黄框向左浮动,脱离了普通流,此时绿框被定位到包含块的左上角 */
            float: left;
            width: 100px;
            height: 80px;
            background: yellow;
            opacity: .5;
        }

        .right {
            width: 200px;
            height: 50px;
            background: green;
            opacity: .5;
        }
    </style>
</head>
<body>
<div class='box'>
    <div class="left"></div>
    <div class="right"></div>
</div>

</body>
</html>

img






特性四

BFC的区域不会与float重叠;

现有如下代码,左盒子设置成浮动,右边是普通的块级div。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>BFC</title>
    <style>
        .box1 {
            /*浮动触发bfc*/
            float: left;
            width: 200px;
            height: 200px;
            background-color: blue;
            text-align: right;
        }

        .box2 {
          
            width: 500px;
         
            height: 300px;
            background-color: yellow;
        }

    </style>
</head>
<body>

<div class="box1">右侧文字</div>
<div class="box2">左侧文字</div>

</body>
</html>

效果如图,左盒子由于被设置成向左浮动,触发了BFC,而右盒子未触发BFC,有部分区域被覆盖了。

img

现在将右盒子也触发BFC。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>BFC</title>
    <style>
        .box1 {
            /*浮动触发bfc*/
            float: left;
            width: 200px;
            height: 200px;
            background-color: blue;
            text-align: right;
        }

        .box2 {
            /*overflow触发bfc, 这里用float:left也行*/  
            overflow: hidden;
            width: 500px;
            height: 300px;
            background-color: yellow;
        }

    </style>
</head>
<body>

<div class="box1">右侧文字</div>
<div class="box2">左侧文字</div>

</body>
</html>

效果如下。

img






特性五

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

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>BFC</title>
    <style>
        .container01 {
            /*触发父盒子bfc*/
            float: left;
            width: 600px;
            border: 2px solid black;
            /*    高度靠内容撑开*/
        }

        .container02{
            /*触发父盒子bfc*/
            float: left;
            width: 600px;
            border: 2px solid black;
        }

        .box1 {
            /*浮动触发bfc*/
            float: left;
            width: 1000px;
            height: 200px;
            background-color: blue;
        }
        .box2 {
            /*浮动触发bfc*/
            float: left;
            width: 1000px;
            height: 200px;
            background-color: yellow;
        }



    </style>
</head>
<body>
<div class="container01">
    <div class="box1">内容</div>
</div>
<div class="container02">
    <div class="box2">内容</div>
</div>

</body>
</html>

效果如图,左右盒子互不干涉。

img





特性六

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

这个就是常见的去浮动的原理,触发BFC,面试中经常会问到的。

现有如下代码。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>BFC</title>
    <style>
        .container {
            width: 600px;
            border: 2px solid black;
            /*    高度靠内容撑开*/
        }

        .box1 {
            /*浮动触发bfc*/
            float: left;
            width: 200px;
            height: 200px;
            background-color: blue;
        }


    </style>
</head>
<body>
<div class="container">
    <div class="box1">内容</div>
</div>

</body>
</html>

效果如下图,可以看到,由于子盒子的浮动,父盒子的高度未被子盒子撑开,因而塌陷了。

img

这时触发父元素形成BFC,就会将浮动元素的高度也计算入内了。

 .container {
            /*触发父盒子bfc*/
            overflow: hidden;
            width: 600px;
            border: 2px solid black;
            /*    高度靠内容撑开*/
}

img





BFC应用场景

自适应两栏布局

现有如下代码,想要实现一个自适应的两栏布局。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        div {
            width: 300px;
        }

        .aside {
            width: 100px;
            height: 150px;
            float: left;
            background: black;
        }

        .main {
            height:200px;
            background-color:red;
        }
    </style>
</head>
<body>
<div class="aside"></div>
<div class="main"></div>
</body>
</html>

效果如图。

img

现在想要将黑色区域和红色区域分开来,不允许有重叠。

因为body本身就是一个BFC,这满足了规范的第三条:

  • 每个元素的左边,与包含的盒子的左边相接触,即使存在浮动也是如此。

所以如果我们需要将黑色区域撑到红色的左边,就需要利用规范的第四条:

  • BFC的区域不会与float重叠。

也就是说我们需要创造BFC区域。可以通过将红色区域的overflow设为hidden来触发BFC:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        div {
            width: 300px;
        }

        .aside {
            width: 100px;
            height: 150px;
            float: left;
            background: black;
        }

        .main {
            /*形成BFC*/
            overflow:hidden;

            height:200px;
            background-color:red;
        }
    </style>
</head>
<body>
<div class="aside"></div>
<div class="main"></div>
</body>
</html>

img






清除浮动

现有如下代码。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>BFC</title>
    <style>
        .container {
            width: 600px;
            border: 2px solid black;
            /*    高度靠内容撑开*/
        }

        .box1 {
            /*浮动触发bfc*/
            float: left;
            width: 200px;
            height: 200px;
            background-color: blue;
        }


    </style>
</head>
<body>
<div class="container">
    <div class="box1">内容</div>
</div>

</body>
</html>

效果如下图,可以看到,由于子盒子的浮动,父盒子的高度未被子盒子撑开,因而塌陷了。

img

这时触发父元素形成BFC,就会将浮动元素的高度也计算入内了。

 .container {
            /*触发父盒子bfc*/
            overflow: hidden;
            width: 600px;
            border: 2px solid black;
            /*    高度靠内容撑开*/
}

img

margin重叠

先定义两个垂直的div:

<div class="p"></div>
<div class="p"></div>

然后定义margin:

.p {
    width:200px;
    height:50px;
    margin:50px 0;
    background-color:red;
}

可以看到margin重叠后的效果:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .p {
            width: 200px;
            height: 50px;
            margin: 50px 0;
            background-color: red;
        }
    </style>
</head>

<body>
<div class="p"></div>
<div class="p"></div>
</body>
</html>

img

再看看BFC规范的第二条:

  • 盒子垂直方向的距离由margin决定,属于用一个BFC的两个相邻Box的上下margin会发生重叠。

说明两者属于同一个BFC,所以我们需要两个div不属于同一个BFC。
为第二个div套一个父亲div,然后将其overflow设为hidden来激活一个BFC就可以使margin不再重叠。

<div class="p"></div>
<div class="wrap">
	<div class="p"></div>
</div>
.wrap {
	overflow:hidden;
}

最终效果如下。

img

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值