什么是BFC?聊聊BFC及其应用

什么是BFC?这个在刚接触前端时候一直困扰自己的东西,知道如何用却不知道原理。
正所谓知其然,知其所以然,今天来对它做一个总结!

什么是BFC?

BFC 一直是面试躲不过的一个命题,之前也看过很多篇文章,但是讲的都相似却讲不清楚,只聊使用却不聊原理,所以一直也记不住。今天通过看其他文章并融入自己的理解作一次总结,希望有所帮助。

在此之前,我们先了解一下FC是什么:

看下W3c文档对标准流和formatting context的解释:

Boxes in the normal flow belong to a formatting context, which may be block or inline, but not both simultaneously. Block-level boxes participate in a block formatting context. Inline-level boxes participate in an inline formatting context.

从中我们能得到如下信息:

  • 所有盒子都属于一个FC
  • 块级元素的布局属于一个BFC。例如div/p等
  • 行内元素的布局属于一个IFC。例如span img等

简而言之 - 块级元素所在的布局和上下文就是BFC(Block Formatting Context) - 行内级元素所在的布局和上下文就是IFC(Inline Formatting Context)

怎样能创建BFC?BFC在哪里?

MDN上作了如下解释(形成BFC的条件):

除了文档的根元素 () 之外,还将在以下情况下创建一个新的 BFC:

  • 使用float 使其浮动的元素
  • 绝对定位的元素 (包含 position: fixed 或position: sticky
  • 使用以下属性的元素 display: inline-block
  • 表格单元格或使用 display: table-cell, 包括使用 display: table-* 属性的所有表格单元格
  • 表格标题或使用 display: table-caption 的元素
  • 块级元素的 overflow 属性不为 visible
  • 元素属性为 display: flow-root 或 display: flow-root list-item
  • 元素属性为 contain: layout, content, 或 strict
  • flex items
  • 网格布局元素
  • multicol containers
  • 元素属性 column-span 设置为 all

理解:html是一个BFC, 但是body不是一个BFC,overflow属性除了visible外都是一个BFC

下面我们作如下示例来加深理解:

<!DOCTYPE html>
<html>
  <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>BFC</title>
  </head>
  <body>
    <div class="box1"></div>
    <div class="box2"></div>
  </body>
</html>

这段代码中的box1和box2就都是在html根元素的BFC中布局的。

BFC的应用

解决margin重叠问题

margin重叠问题原因:

In a block formatting context, boxes are laid out one after the other, vertically, beginning at the top of a containing block. The vertical distance between two sibling boxes is determined by the ‘margin’ properties. Vertical margins between adjacent block-level boxes in a block formatting context collapse.
In a block formatting context, each box’s left outer edge touches the left edge of the containing block (for right-to-left formatting, right edges touch). This is true even in the presence of floats (although a box’s line boxes may shrink due to the floats), unless the box establishes a new block formatting context (in which case the box itself href=“https://www.w3.org/TR/CSS2/visuren.html#bfc-next-to-float”>may become narrower due to the floats).

从中我们可以了解到:

  • 在BFC中,box会在垂直方向一个挨着一个进行排列,因此块级元素会独占一行
  • 垂直方向上的距离由margin决定
  • 同一个BFC中,相邻的两个块之间会出现margin折叠(取两者之间较大的,可使用此特性解决margin重叠问题)
  • 在BFC中,每个元素左边缘都是紧挨包含块左边缘的。html就是一个BFC,因此每一个元素都是默认靠左对齐。

margin重叠问题解决:

<!DOCTYPE html>
<html>
  <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>BFC</title>
    <style>
      .box1 {
      
      
        height: 200px;
        width: 400px;
        background-color: red;

        margin-bottom: 30px;
      }
      .box2 {
      
      
        height: 150px;
        width: 400px;
        background-color: burlywood;

        margin-top: 50px;
      }
    </style>
  </head>
  <body>
    <div class="box1"></div>
    <div class="box2"></div>
  </body>
</html>

此时box1和box2同事处于html的BFC中,所以会出现margin重叠的情况,取50px;
在这里插入图片描述
所以我们如果让它们不在同一个BFC中,就可以解决这个问题:

<html>
  <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>BFC</title>
    <style>
      .box1 {
      
      
        height: 200px;
        width: 400px;
        background-color: red;

        margin-bottom: 30px;
      }
      .box2 {
      
      
        height: 150px;
        width: 400px;
        background-color: burlywood;

        margin-top: 50px;
      }
	  .top{
      
      
	    overflow: hidden;
	  }
    </style>
  </head>
  <body>
    <div class="top">
      <div class="box1"></div>
    </div>
    <div class="box2"></div>
  </body>
</html>

这样我们给box1加一层父元素,并加属性overflow:hidden让box1处于新的BFC下,就可以让box1和box2处于不同的BFC,也就解决了margin重叠的问题。
在这里插入图片描述

解决高度塌陷的问题

当dom设置float浮动后,浮动元素会脱离文档流,导致父元素高度塌陷。见下面例子:

<html>
  <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>BFC</title>
    <style>
      .container {
      
      
        background-color: orange;
		padding:10px;
      }
      .item {
      
      
        width: 400px;
        height: 200px;
        box-sizing: border-box;
        border: 1px solid #000;
        float: left;
        background-color: #f00;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <div class="item"></div>
      <div class="item"></div>
      <div class="item"></div>
      <div class="item"></div>
    </div>
  </body>
</html>

在这里插入图片描述
为了可以看清父元素(橙色),我加了10px的padding值,我们可以看到设置了float的item并没有撑起父元素container的高度(此时container高度为0)。

此时想解决高度塌陷问题需要满足两个条件:

  • 浮动元素的父元素触发BFC,形成独立的块级格式化上下文。
  • 浮动元素的父元素高度为auto。

因此我们给.container加上“overflow:hidden”即可。(不绝对,只要让父元素触发BFC即可)
在这里插入图片描述
当BFC高度是auto时,高度是这样计算的:

  • 如果只有inline-level,是行高的顶部和底部的距离
  • 如果有block-level,是有最底层的块上边缘和最底层块盒子的下边缘之间的距离(有margin也会计算在内)
  • 如果有绝对定位元素,将被忽略(所有我们无法通过BFC解决绝对定位的高度塌陷问题)
  • 如果有浮动元素,那么会增加高度以包括这些浮动元素的下边缘(这才是BFC能解决浮动元素塌陷问题的原因,并不是因为浮动元素向上汇报了高度)

以上就是今日的分享!希望对大家理解BFC有所帮助。

猜你喜欢

转载自blog.csdn.net/hanyanshuo/article/details/127307086
BFC
今日推荐