CSS块级格式化上下文(BFC)与清除浮动详解

1. 什么是BFC

BFC,英文名 Block formatting context,直译为“块级格式化上下文”。它是W3C CSS 2.1规范中的一个概念,决定了元素如何对内容进行定位,以及与其他元素的关系相互作用

2.BFC元素所具有的特性

  • 1.在同一个BFC内的两个相邻块级元素的外边距会重叠,但不同 BFC外边距不会重叠
  • 2.在计算BFC高度时,将它内部的浮动元素也包含在内。
  • 3.BFC的区域不会与外部浮动元素重叠

它是一个独立的渲染区域,只有Block-level box参与, 它规定了内部的Block-level Box如何布局,并且与这个区域外部毫不相干。(白话文: 孩子在家里愿意怎么折腾都行,但是出了家门口,你就的乖乖的,不能影响外面的任何人。)

3.如何创建BFC

MDN CSS developer guide 给出创建BFC的方法常用的有以下几种:

  • 1、 根元素
  • 2、 float属性不为none
  • 3、 position为absolute或fixed
  • 4、 overflow的值不为visible
  • 5、 display的值为table-cell,table-caption,inline-block中的任何一个。
  • 6、弹性元素(display为 flex 或 inline-flex元素的直接子元素)
    另外: 匿名表格单元格元素(元素的 display为 table等)

4.BFC的应用场景

1. 解决块级元素垂直方向的边距重叠问题

由于块级元素垂直方向的边距会发生重叠,div间距并不是50px+100px,而是100px(较大的margin值)。

    <style>
      .top {
        background-color: blue;
        width: 100px;
        height: 100px;
        margin-bottom: 50px;
      }
      .bottom {
        height: 100px;
        width: 100px;
        margin-top: 100px;
        background-color: #ccc;
        /* display: flex; */
        /* overflow: hidden; */
      }
    </style>
    <div class="main">
      <div class="top"></div>
      <div class="bottom"></div>
    </div>

在这里插入图片描述
原因是因为,它们属于同一个BFC(根元素),外边距是会重叠滴。所以只要将它们其中一个属于另一个BFC,就可以啦。

<div class="main">
      <div class="top"></div>
      <div style="overflow: hidden;">
        <div class="bottom"></div>
      </div>
</div>

在这里插入图片描述

2.解决元素浮动后发生重叠的问题(自适应布局)

右边自适应布局

如图,左边的元素浮动之后,由于脱离标准文档流叠在了右边的元素上,为了让两个元素不重叠,我们把右边的元素设置成BFC:
在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      .left {
        background-color: blue;
        width: 100px;
        height: 80px;
        float: left;
      }
      .content {
        height: 100px;
        background-color: #ccc;
        /* display: flex; */
        /* display: table-cell;
        width: 9000px; */
        overflow: hidden;
      }
    </style>
  </head>
  <body>
    <div class="main">
      <div class="left"></div>
      <div class="content">
        start,nt,content,content,content,end.....
      </div>
    </div>
  </body>
</html>

在这里插入图片描述
一个右边自适应的布局就完成了。

中间自适应布局

同理,我们可以搞一个中间自适应布局,代码如下(注意left和right盒子的位置)

  <body>
    <style>
      .left {
        background-color: blue;
        width: 100px;
        height: 80px;
        float: left;
      }
      .right {
        background-color: pink;
        width: 100px;
        height: 80px;
        float: right;
      }
      .content {
        height: 100px;
        background-color: #ccc;
        /* display: flex; */
        overflow: hidden;
      }
    </style>
    <div class="main">
      <div class="left"></div>
      <div class="right"></div>
      <div class="content">
        start,nt,content,content,content,end.....
      </div>
    </div>
  </body>

在这里插入图片描述

3.清除浮动

1.overflow: hidden清除浮动(计算BFC浮动元素高度)

如下代码,

  <body>
    <style>
      .main {
        border: 1px solid red;
      }
      .content {
        height: 100px;
        width: 100px;
        background-color: #ccc;
        float: left;
      }
    </style>
    <div class="main">
      <div class="content"></div>
    </div>
  </body>

在这里插入图片描述
子元素浮动后,父元素失去了高度,为了清除浮动带来的这个影响可以将父元素设置成一个BFC:

.main {
    border: 1px solid red;
    overflow: hidden;
}

在这里插入图片描述
这是因为在计算BFC高度时,将它内部的浮动元素也包含在内。

缺点:会导致溢出隐藏。

2.clear:both 清除浮动

常规的解决方法就是利用clear来清除浮动

<div class="main">
  <div class="content"></div>
  <div style="clear: both;"></div>
</div>

缺点: 添加许多无意义的标签,结构化较差。

3.利用伪元素和BFC清除浮动

用法:直接应用在父元素上就行。

1.使用after伪元素清除浮动

 .clearfix::before, .clearfix::after {
   content: '';
   display: block;
   height: 0;
   /* font-size: 0; */
   visibility: hidden;
   clear: both;
 }
 .clearfix {
   *zoom: 1;
 }

2.使用双伪元素清除浮动
这是bootstrap上使用的方法。

.clearfix::before,
.clearfix::after {
  content: '';
  display: table;
  /* font-size: 0; */
}
.clearfix::after {
  clear: both;
}
.clearfix {
  *zoom: 1;
}

解析:

  • :after伪类在元素末尾插入了一个包含空格的字符,并设置display为table
  • display:table会创建一个匿名的table-cell,从而触发块级上下文(BFC),因为容器内float的元素也是BFC,由于BFC有不能互相重叠的特性,并且设置了clear: both,:after插入的元素会被挤到容器底部,从而将容器撑高。并且设置display:table后,content中的空格字符会被渲染为0*0的空白元素,不会占用页面空间。
  • content包含一个空格,是为了解决Opera浏览器的BUG。当HTML中包含contenteditable属性时,如果content没有包含空格,会造成清除浮动元素的顶部、底部有一个空白(设置font-size:0也可以解决这个问题)。
  • :after伪类的设置已经达到了清除浮动的目的,但还要设置:before伪类,原因如下
    • :before的设置也触发了一个BFC,由于BFC有内部布局不收外部影响的特性,因此:before的设置可以阻止margin-top的合并。(我试了没效果…
    • 这样做,其一是为了和其他清除浮动的方式的效果保持一致;其二,是为了与ie6/7下设置zoom:1后的效果一致(即阻止margin-top合并的效果)。
  • zoom: 1用于在ie6/7下触发haslayout和contain floats

总结

清除浮动的方式 优点 缺点
额外标签法(隔墙法) 通俗易懂,书写方便 添加许多无意义的标签,结构化较差。
父级overflow:hidden; 书写简单 溢出隐藏
父级after伪元素 结构语义化正确 由于IE6-7不支持:after,兼容性问题
父级双伪元素 结构语义化正确 由于IE6-7不支持:after,兼容性问题

注:现在较少考虑IE低版本的兼容性

参考

W3C:block-formatting
MDN:Block_formatting_context
BFC之浅析篇

BFC的特性及其常见应用
清除浮动
bootstrap中的清除浮动

发布了39 篇原创文章 · 获赞 7 · 访问量 3225

猜你喜欢

转载自blog.csdn.net/tinfengyee/article/details/105657898