CSS - BFC

124 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第23天,点击查看活动详情

FC

FC全称为Formatting Context,也就是格式化上下文

在CSS中,任何一个在标准流中的元素都属于一个FC

块级元素的布局属于Block Formatting Context(BFC)

  • block level box都是在BFC中布局的

行内级元素的布局属于Inline Formatting Context(IFC)

  • inline level box都是在IFC中布局的
  • 本质上 行盒就是一个IFC

BFC

block format context(块级格式化上下文) 是页面的一块渲染区域 并且有一套渲染规则,决定了子元素如何定位 以及与其他元素之间的排列 布局之间的关系

BFC是一个独立的布局环境 相当于是一个容器 在其中按照一定的规则对块级元素进行摆放 ,并且不会影响其他的布局环境中的盒子,如果一个元素触发BFC则BFC中的元素布局不受外界的影响

对于位于BFC中的元素,存在如下特点:

  1. box会在垂直方向上一个挨着一个的排布
  2. 垂直方向的间距由margin属性决定
  3. 在同一个BFC中,相邻两个box之间的margin会折叠(collapse)
  4. 在BFC中,每个元素的左边缘是紧挨着包含块的左边缘的 --- 也就意味着元素默认是左对齐的
  5. BFC内部元素的布局和外部元素的布局互不影响,相互独立

可以开启BFC的元素

  • 根元素(<html>)
  • 浮动元素 (元素的 float 不是 none)
  • 绝对定位元素 (元素的 position 为 absolute 或 fixed)
  • 行内块元素 (元素的 display 为 inline-block)
  • 表格相关元素 (table, th, td, tbody, thead, tr, tfooter, captain等)
  • overflow 计算值(Computed)不为 visible 的块元素
  • 弹性元素(display 为 flex 或 inline-flex 元素的直接子元素)
  • 网格元素(display 为 grid 或 inline-grid 元素的直接子元素)
  • display 值为 flow-root 的元素

最常用的开启元素BFC的方式是,设置overflow: auto,或者使用display: flow-root

因为使用这2种方式开启元素的BFC,所造成的副作用是最小的

BFC的作用

  1. 解决margin的折叠问题

​ 在同一个BFC中,相邻两个box之间的margin会折叠(collapse)

​ 所以只要让两个盒子不在同一个BFC中,这两个相邻的盒子之间的margin就不会发生折叠

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    .box {
      width: 300px;
      height: 300px;
    }

    .container {
      /*
        注意: BFC是决定其子块级元素的排列方式
        所以需要给div.box1的父元素进行开启

        不可以直接开启div.box1的BFC
        因为此时div.box1内容是一个独立的BFC
        但是div.box1本身和div.box2一样都位于同一个BFC中
        皆位于由html开启的BFC中
      */
      display: flow-root;
    }

    .box1 {
      background-color: red;
      margin-bottom: 30px;
    }

    .box2 {
      background-color: blue;
      margin-top: 50px;
    }
  </style>
</head>
<body>
  <div class="container">
    <div class="box box1"></div>
  </div>
  <div class="box box2"></div>
</body>
</html>
  1. 解决浮动高度塌陷问题

使用BFC解决浮动高度塌陷问题有两个前提条件

  1. 浮动元素的父元素触发BFC,形成独立的块级格式化上下文(Block Formatting Context)
  2. 浮动元素的父元素的高度是auto的

此时因为开启BFC的元素高度是auto,那么其高度的计算规则如下:

  • 如果只有inline-level,是行高的顶部和底部的距离 --- 也就是按照行盒的高度来进行计算
  • 如果有block-level,是由最底层的块上边缘和最底层块盒子的下边缘之间的距离 --- 元素的高度 + margin
  • 如果有绝对定位元素,将被忽略, 相对定位元素本质上并没有脱标,所以其高度会被计算在内
  • 如果有浮动元素,那么BFC会增加高度以包括这些浮动元素的下边缘 --- BFC会自动增加高度以包含所有的浮动元素(包括浮动元素的margin也会被包含在内)
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    .container {
      width: 300px;
      background-color: skyblue;
      display: flow-root;
    }

    .item {
      width: 100px;
      height: 100px;
      background-color: red;
      border: 1px solid blue;
      box-sizing: border-box;
      float: left;
    }
  </style>
</head>
<body>
  <div class="container">
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
  </div>
</body>
</html>
  1. 阻止元素被浮动元素覆盖
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    .container {
      width: 300px;
      height: 300px;
      background-color: skyblue;
      line-height: 300px;
      color: #fff;
      text-align: center;
      font-size: 30px;
    }

    .left {
      width: 100px;
      height: 100%;
      float: left;
      background-color: gray;
    }

    .right {
      width: calc(100% - 100px);
      height: 100%;
      background-color: orange;
      display: flow-root;
    }
  </style>
</head>
<body>
  <div class="container">
    <div class="left">left</div>
    <div class="right">right</div>
  </div>
</body>
</html>