通过例子学习BFC

135 阅读5分钟

什么是BFC

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

uh...,好像不太懂。没关系,通过几个小例子来看看这个“神奇”的东东。

BFC解决浮动溢出问题

通过一个简单的浮动示例来看。比如,有一个div,包含一个左浮动的image和一些文字。如果文字特别多的话,就会环绕浮动的图片。

<div class="outer">
    <div class="float">I am a floated element.</div>
    I am text inside the outer box.I am text inside the outer box.
    I am text inside the outer box.I am text inside the outer box.
    I am text inside the outer box.I am text inside the outer box.
</div>
.outer {
    border: 5px dotted rgb(214,129,137);
    border-radius: 5px;
    width: 450px;
    padding: 10px;
    margin-bottom: 40px;
}

.float {
    padding: 10px;
    border: 5px solid rgba(214,129,137,.4);
    border-radius: 5px;
    background-color: rgba(233,78,119,.4);
    color: #fff;
    float: left;  
    width: 200px;
    margin: 0 20px 0 0;
}

结果:

如果删除一些文字,使它无法环绕图片时,div的边框就会在浮动元素的下面。因为浮动的元素是脱离文档流的,div的宽度不变,高度即为文字的高度,当文字较少时,文字高度低于图片的高度,就会导致div的边框在image的下面。

通常有两种方法来解决这个布局问题,一个是使用clearfix hack,在图片和文本下面插入一个元素,并将其设置为clear:both。另一种方法是使用overflow属性,其值不是默认的visible。

.outer {
    ...
    overflow: auto;
}

overflow之所以有用,是因为使用visible以外任何值都会创建一个块格式化上下文(BFC),BFC的特性之一就是它包含浮动元素

BFC可以解决外边距重叠问题

比如有一个background为grey的div,div中有两个p元素。div的margin-bottom是40px,p元素的margin-top, margin-bottom各为20px。

<div class="outer">
    <p>I am paragraph one and I have a margin top and bottom of 20px</p>
    <p>I am paragraph two and I have a margin top and bottom of 20px</p>
</div>
.outer {
    background-color: #ccc;
    margin: 0 0 40px 0;
}

p {
    padding: 0;
    margin: 20px 0 20px 0;
    background-color: rgb(233,78,119);
    color: #fff;
}

由于p元素的边距与外部div的边距之间没有任何内容,这两个边距将会重叠,因此段落将与框的顶部和底部齐平,所以看不到第一个p元素上面的灰色部分,和第二个p元素下面的灰色部分。MDN-外边距重叠

如果我们把div设置成BFC,那么就可以看到边距后的容器的灰色背景了。

.outer {
    ...
    overflow: auto;
}

再一次,BFC的工作是把东西装在盒子里,防止它们从盒子里跑出来

BFC可以解决内容包裹浮动元素问题

比如一个div包含一个左浮动的元素,和一段文本内容。

<div class="outer">
    <div class="float">I am a floated element.</div>
    <div class="text">
        I am textI am textI am textI am textI am text
        I am textI am textI am textI am textI am textI am textI am text
        I am textI am textI am textI am text
    </div>
</div>
.outer {
    border: 5px dotted rgb(214,129,137);
    border-radius: 5px;
    width: 450px;
    padding: 10px;
    margin-bottom: 40px;
    overflow: auto;
}

.float {
    padding: 10px;
    border: 5px solid rgba(214,129,137,.4);
    border-radius: 5px;
    background-color: rgba(233,78,119,.4);
    color: #fff;
    float: left;  
    width: 200px;
    margin: 0 20px 0 0;
}

当文本内容过长时,便会包裹浮动元素。

可以通过将包装文本的div设置为BFC来防止这种包裹行为。

.text {
  overflow: auto;
}

这个其实也是创建有多列的浮动布局的方式。浮动元素本身也会创建一个BFC,所以即使右边的内容比左边的高,也不会包裹左边的元素。

BFC是布局中的一个迷你布局

你可以把BFC想象成页面内部的一个小布局。一旦一个元素创建了一个BFC,元素里面的内容都包含在其中。

块格式化上下文对浮动定位与清除浮动都很重要。浮动定位和清除浮动时只会应用于同一个BFC内的元素。浮动不会影响其它BFC中元素的布局,而清除浮动只能清除同一BFC中在它前面的元素的浮动。外边距折叠也只会发生在属于同一BFC的块级元素之间。

创建BFC的方式

  • 根元素()
  • 浮动元素(元素的 float 不是 none)
  • 绝对定位元素(元素的 position 为 absolute 或 fixed)
  • 行内块元素(元素的 display 为 inline-block)
  • position: absolute/fixed;
  • display: inline-block , table-cell , table-caption。table-cell和table-caption是HTML元素的默认设置,因此table的每个单元格将创建一个BFC。
  • overflow 值不为 visible 的块元素
  • display 值为 flow-root 的元素。它可以创建无副作用的BFC。在父级块中使用 display: flow-root 可以创建新的BFC
  • contain 值为 layout、content或 paint 的元素
  • 弹性元素(display为 flex 或 inline-flex元素的直接子元素)
  • 网格元素(display为 grid 或 inline-grid 元素的直接子元素)
  • 多列容器(元素的 column-count 或 column-width 不为 auto,包括 column-count 为 1)
  • column-span 为 all的元素始终会创建一个新的BFC,即使该元素没有包裹在一个多列容器中)。

最后如果还是糊里糊涂,那就再翻翻MDN的讲解,配合一些小例子效果更佳哟。