BFC — 张天禹

本文介绍了BFC(BlockFormattingContext)的概念,解释了它如何解决元素间的margin塌陷、浮动元素覆盖和父元素高度塌陷等问题。通过示例演示了如何通过浮动、绝对定位、display属性等方法开启BFC,并展示了在实际布局中的应用场景。
摘要由CSDN通过智能技术生成

学习链接

什么是BFC?看这一篇就够了

BFC

1. 什么是BFC

W3C 上对 BFC 的定义

原文:Floats, absolutely positioned elements, block containers (such as inline-blocks, tablecells, and table-captions) that are not block boxes, and block boxes with ‘overflow’ other than ‘visible’ (except when that value has been propagated to the viewport) establish new block formatting contexts for their contents.

译文:浮动绝对定位元素不是块盒子的块容器(如 inline-blocks 、 table-cells 和table-captions ),以及 overflow 属性的值除 visible 以外的块盒,将为其内容建立新的块格式化上下文

MDN 上对 BFC 的描述

块格式化上下文(Block Formatting Context,BFC) 是 Web 页面的可视 CSS 渲染的一部分,是块盒子的布局过程发生的区域,也是浮动元素与其他元素交互的区域。

更加通俗的描述

  1. BFC 是 Block Formatting Context (块级格式上下文),可以理解成元素的一个“特异功能”。

  2. 该 “特异功能”,在默认的情况下处于关闭状态;当元素满足了某些条件后,该“特异功能被激活

  3. 所谓激活“特异功能”,专业点说就是:该元素创建了 BFC (又称:开启了 BFC )。

2. 开启了BFC能解决什么问题

  1. 元素开启 BFC 后,其子元素不会再产生 margin 塌陷问题。
  2. 元素开启 BFC 后,自己不会被其他浮动元素所覆盖。
  3. 元素开启 BFC 后,就算其子元素浮动,元素自身高度也不会塌陷。

3. 如何开启BFC

  • 根元素
  • 浮动元素
  • 绝对定位、固定定位的元素
  • 行内块元素
  • 表格单元格: table 、 thead 、 tbody 、 tfoot 、 th 、 td 、 tr 、 caption
  • overflow 的值不为 visible 的块元素
  • 伸缩项目
  • 多列容器
  • column-span 为 all 的元素(即使该元素没有包裹在多列容器中)
  • display 的值,设置为 flow-root

演示

演示1

子元素margin塌陷问题

  • outer仅设置宽度
  • inner设置宽度和高度,以及margin
  • 可以看到子元素把父元素给拉下来了,最后1个子元素的margin-bottom也给父元素剥夺了

在这里插入图片描述

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>01_BFC_演示1</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        
        /* outer仅设置宽度 */
        .outer {
            width: 400px;
            background-color: #888;
           
        }
        
        /* inner设置宽度和高度,以及margin */
        .inner {
            width: 100px;
            height: 100px;
            margin: 20px;
        }
        
        .inner1 {
            background-color: orange;
        }
        
        .inner2 {
            background-color: green;
        }
        
        .inner3 {
            background-color: deepskyblue;
        }
    </style>
</head>
<body>
    <div class="outer">
        <div class="inner inner1"></div>
        <div class="inner inner2"></div>
        <div class="inner inner3"></div>
    </div>
    <hr style="height: 50px; background-color: red;">
</body>
</html>

使用BFC解决问题

  • 使用以下任意方式都能解决问题
  • 其中,伸缩项目是通过设置body为flex,则body的直接子元素变成伸缩项目了
  • display设置为flow-root;是新定义出来的属性值
  • overflow设置只要不为visible,包括auto都可以开启BFC

在这里插入图片描述

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>01_BFC_演示1</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        body {
            /* display: flex; */
        }
        .outer {
            width: 400px;
            background-color: #888;
            float: left; 
            /* position: absolute; */
            /* display: inline-block; */
            /* display: table; */
            /* overflow: auto; */
            /* column-count: 1; */
            /* display: flow-root; */
        }
        .inner {
            width: 100px;
            height: 100px;
            margin: 20px;
        }
        .inner1 {
            background-color: orange;
        }
        .inner2 {
            background-color: green;
        }
        .inner3 {
            background-color: deepskyblue;
        }
    </style>
</head>
<body>
    <div class="outer">
        <div class="inner inner1"></div>
        <div class="inner inner2"></div>
        <div class="inner inner3"></div>
    </div>
    <hr style="height: 50px; background-color: red;">
</body>
</html>

完美解决塌陷问题

  • 注意:给outer设置border,也能解决父子元素垂直外边距塌陷的问题,但这并没有开启BFC。并且设置border相当于改了盒子尺寸了,这是个副作用,其实就相当于让父子元素外边距不相邻了
  • 其实,不用上面的BFC也能完美解决这个问题,效果如下:

在这里插入图片描述

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>01_BFC_演示1</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        
        .outer {
            width: 400px;
            background-color: #888;
            
        }

		/* 既能解决父子元素相邻外边距问题,
		   又能解决子元素浮动造成父元素高度的塌陷问题 */
        .clearfix::before,
        .clearfix::after {
            content: "";
            display: table;
            clear: both;
        }


        .inner {
            width: 100px;
            height: 100px;
            margin: 20px;
        }
        .inner1 {
            background-color: orange;
        }
        .inner2 {
            background-color: green;
        }
        .inner3 {
            background-color: deepskyblue;
        }
    </style>
</head>
<body>

    <div class="outer clearfix">
        <div class="inner inner1"></div>
        <div class="inner inner2"></div>
        <div class="inner inner3"></div>
    </div>
    
    <hr style="height: 50px; background-color: red;">
</body>
</html>

演示2

被浮动元素覆盖问题

  • box1浮动起来,这样,自然box2就顶山去了,但是box1盖在了box2的上面,这样就是1个问题了
    在这里插入图片描述
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>02_BFC_演示2</title>
    <style>
    
        body {
            margin: 0;
        }
        .outer {
            border: 2px solid red;
        }
        
        .box1 {
            width: 100px;
            height: 100px;
            background-color: orange;
            float: left;
        }
        
        .box2 {
            width: 120px;
            height: 120px;
            background-color: green;
            
        }
    </style>
</head>
<body>
    <div class="outer">
        <div class="box1"></div>
        <div class="box2"></div>
    </div>
</body>
</html>

使用BFC解决问题

例1
  • 让box2也浮动起来,这样box1就盖不到box2(纳闷:这不就2个浮动的么,开啥BFC),反正box2是通过浮动开启了BFC,box1就休想盖到box2上面,这也符合BFC解决问题的范畴
    在这里插入图片描述
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>02_BFC_演示2</title>
    <style>
        body {
            margin: 0;
        }
        .outer {
            border: 2px solid red;
        }
        .box1 {
            width: 100px;
            height: 100px;
            background-color: orange;
            float: left;
        }
        .box2 {
            width: 120px;
            height: 120px;
            background-color: green;
            float: left;
        }
    </style>
</head>
<body>
    <div class="outer">
        <div class="box1"></div>
        <div class="box2"></div>
    </div>
</body>
</html>
例2
  • box2直接设置绝对定位,box1确实无法盖住box2,因为box2已经把box1给盖住了
    在这里插入图片描述
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>02_BFC_演示2</title>
    <style>
        body {
            margin: 0;
        }
        .outer {
            border: 2px solid red;
        }
        .box1 {
            width: 100px;
            height: 100px;
            background-color: orange;
            float: left;
        }
        .box2 {
            width: 120px;
            height: 120px;
            background-color: green;
            
            position: absolute;
            opacity: 0.6;
           
        }
    </style>
</head>
<body>
    <div class="outer">
        <div class="box1"></div>
        <div class="box2"></div>
    </div>
</body>
</html>
例3
  • 现在给box2设置inline-block,由于box2开启了BFC,那么box1就无法盖住box2(浮动本来就是用来作文字环绕的),但是下面有1个小缝
    在这里插入图片描述
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>02_BFC_演示2</title>
    <style>
        body {
            margin: 0;
        }
        .outer {
            border: 2px solid red;
        }
        .box1 {
            width: 100px;
            height: 100px;
            background-color: orange;
            float: left;
        }
        .box2 {
            width: 120px;
            height: 120px;
            background-color: green;
           
            display: inline-block;
           
        }
    </style>
</head>
<body>
    <div class="outer">
        <div class="box1"></div>
        <div class="box2"></div>
    </div>
</body>
</html>
例4
  • 给box2设置overflow为auto,浮动的box1没有盖住box2,并且下面也是没有缝隙的(相比例3中中设置box2的display为inline-block)

在这里插入图片描述

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>02_BFC_演示2</title>
    <style>
        body {
            margin: 0;
        }
        .outer {
            border: 2px solid red;
        }
        .box1 {
            width: 100px;
            height: 100px;
            background-color: orange;
            float: left;
        }
        .box2 {
            width: 120px;
            height: 120px;
            background-color: green;
          
            overflow: auto;
          
        }
    </style>
</head>
<body>
    <div class="outer">
        <div class="box1"></div>
        <div class="box2"></div>
    </div>
</body>
</html>
延申(左右布局)
  • 既然浮动元素不能盖住开启了BFC的元素,而且在例4中,我们看到浮动元素box1和overflow:hidden的box2元素处于同一行,那么如果我们不给box2设置宽度,又会怎么样呢?如下,我们可以做成基本的左右布局效果。
  • 下面,我们不设置box2的宽度(不要设置为100%),并且,设置box2的overflow:auto或hidden都可以
    在这里插入图片描述
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>02_BFC_演示2</title>
    <style>
        body {
            margin: 0;
        }
        .outer {
            border: 2px solid red;
        }
        .box1 {
            width: 100px;
            height: 100px;
            background-color: orange;
            float: left;
        }
        .box2 {
            height: 120px;
            background-color: green;
          
            overflow: auto;
          
        }
    </style>
</head>
<body>
    <div class="outer">
        <div class="box1"></div>
        <div class="box2"></div>
    </div>
</body>
</html>

演示3

浮动造成父元素高度塌陷问题

  • 当父元素未设置高度,子元素又都浮动起来,这个时候父元素的高度就会塌陷,这种情况,也可以使用上面提到的完美解决塌陷问题的方案,但在这里,我们通过开启父元素的BFC解决

使用BFC解决问题

在这里插入图片描述

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>03_BFC_演示3</title>
    <style>
        body {
            margin: 0;
        }
        .outer {
            width: 400px;
            background-color: #888;
            /* float: left; */
            /* position: absolute; */
            /* display: inline-block; */
            /* display: table; */
            /* overflow: auto; */
            /* column-count: 1; */
            /* display: flow-root; */
        }
        .inner {
            width: 100px;
            height: 100px;
            float: left;
        }
        .inner1 {
            background-color: orange;
        }
        .inner2 {
            background-color: green;
        }
    </style>
</head>
<body>
    <div class="outer">
        <div class="inner inner1"></div>
        <div class="inner inner2"></div>
    </div>
</body>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值