什么是BFC?BFC有什么用?BFC怎么用?

1,218 阅读4分钟

BFC的定义

BFC全称“Block Formatting Context”, 中文为“块级格式化上下文”。它是一个独立的渲染区域,只有Block-level box参与, 它规定了内部的Block-level Box如何布局,并且与这个区域外部毫不相干。 在解释什么是BFC之前,我们需要先知道BoxFormatting Context的概念。

Box:css布局的基本单位

BoxCSS布局的对象和基本单位,一个页面是由很多个Box组成的。元素的类型和display属性,决定了这个Box的类型。不同类型的Box,会参与不同的Formatting Context,会以不同的方式渲染。主要的Box(盒子)类型有:

  • block-level box: display属性为block, inline-block, list-item, table的元素,会生成block-level box,并且参与block fomatting context
  • inline-level box: display属性为inline, inline-block, inline-table的元素,会生成inline-level box,并且参与inline formatting context
  • run-in box: css3中才有, 这儿先不讲了。

Formatting Context:决定如何渲染文档的容器

Formatting contextW3C CSS2.1规范中的一个概念。它是页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用。最常见的Formatting contextBlock fomatting context(简称BFC)和Inline formatting context(简称IFC)。 BFC是一个独立的布局环境,其中的元素布局是不受外界的影响,并且在一个BFC中,块盒与行盒(行盒由一行中所有的内联元素所组成)都会垂直的沿着其父元素的边框排列。BFC元素特性表现原则就是,内部子元素再怎么翻江倒海,翻云覆雨都不会影响外部的元素,外部元素也不会影响到BFC内部的元素布局。

BFC的布局规则

  • 内部的Box会在垂直方向,一个接一个地放置。
  • Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Boxmargin会发生重叠。
  • 每个盒子(块盒与行盒)的margin box的左边,与包含块border box的左边相接触(对于从左往右的格式化,否则相反),即使存在浮动也是如此。
  • BFC的区域不会与float box重叠。
  • BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素,反之亦然。
  • 计算BFC的高度时,浮动元素也参与计算。

如何创建BFC

  1. 根元素,即html
  2. float的值不是none。(leftright
  3. overflow的值不是visible。(autoscrollhidden
  4. position的值不是static或者relative。(absolutefixed
  5. display的值是inline-blockinline-flexflextable-celltable-caption

BFC的作用

避免margin重叠(穿透)###

根元素下的两个元素都不是BFC的效果:

<p>1--看看我的margin是多少</p>
<p>2--看看我的margin是多少</p>
*{
    margin: 0;
    padding: 0; // 清除所有标签的marginpadding避免干扰
}
p {
    color: #f55;
    background: yellow;
    width: 200px;
    line-height: 100px;
    text-align:center;
    margin: 30px;
}

可以看到同属于HTML下的两个P标签的margin重叠,原因就是BFC的布局规则第二条所讲的属于同一个BFC的两个相邻Boxmargin会发生重叠。 那把其中一个P标签变成BFC就能解决margin重叠的问题: 给第一个P标签包裹一个div。为什么需要包裹?因为P中的内容不是Block-level box,没有margin属性,因此包上一层div,给div设置样式overflow: hidden(非visible即可),里面的PBlock-level boxmargin属性,就能看到两个P标签的margin都生效且不重叠。

<div>
    <p>1--看看我的margin是多少</p>
</div>
<p>2--看看我的margin是多少</p>
div{
    overflow: hidden;
}

自适应两栏布局###

根据BFC的布局规则第三条:每个盒子的margin box的左边,与包含块border box的左边相接触(对于从左往右的格式化,否则相反),即使存在浮动也是如此:

<div class="left">LEFT float-left</div>
<div class="right">RIGHT</div>
*{
    margin: 0;
    padding: 0;
}
body {
    margin-left: 50px; /* 测试包含块border box的左边 */
    border-left: 1px solid red; /* 测试包含块border box的左边 */
}
.left {
    width: 150px;
    height: 150px;
    float: left;
    background: rgb(139, 214, 78);
    text-align: center;
    line-height: 150px;
    font-size: 20px;
}

.right {
    height: 300px;
    background: rgb(170, 54, 236);
    text-align: center;
    line-height: 300px;
    font-size: 40px;
    margin-left: 20px; /* 测试盒子的margin box的左边 */
}

浮动的.left和正常的.rightmargin box左边都与包含块border box的左边相接触 要实现两栏布局,根据BFC的布局规则第四条:BFC的区域不会与float box重叠,给.right盒子设置overflow:hidden(非visible即可)。

清除浮动

当我们不给父节点设置高度,子节点设置浮动的时候,会发生高度塌陷,这个时候我们就要清楚浮动。

<div class="par">
    <div class="child"></div>
    <div class="child"></div>
</div>
.par {
    border: 5px solid rgb(91, 243, 30);
    width: 300px;
}
.child {
    border: 5px solid rgb(233, 250, 84);
    width:100px;
    height: 100px;
    float: left;
}

根据BFC的布局规则最后一条:计算BFC的高度时,浮动元素也参与计算,给父节点激活BFC 参考链接