愿你坚持不懈,努力进步,进阶成自己理想的人

—— 2017.09, 写给3年后的自己

理解BFC(块级格式化上下文)

BFC是Block Formatting Context的缩写,全称为块级格式化上下文。BFC也是一个盒子(只不过看不见)

一、如何形成BFC

满足以下条件之一,便可形成BFC:

  • float属性不为none
  • postion属性不为staticrelative(即为absolutefixed
  • display为table-celltable-captioninline-blockflexinline-flex之一
  • overflow的属性不为visible

虽然有如此多的条件可以形成BFC,但是不少条件会有些多多少少的副作用(属性设置带来的表现),如:

  • overflow: scroll 会有滚动条
  • float: left 使元素浮动

所以,其实建立BFC最好的方式,便可以是overflow: hidden


二、BFC布局

根据W3C规范:

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 may become narrower due to the floats)

翻译过来则是:

在块级格式化上下文(BFC)中,每个盒子的左边界,都向着容纳块(Containing block)的左边靠齐(对于右到左格式,则是向右靠齐)。对于float的情况下,也是如此(尽管一个盒子的线框可能会因为浮动而缩小),除非盒子建立了一个新的BFC(某些情况下盒子本身会因为浮动而变得狭小)

所以,BFC有什么用呢?


三、BFC应用

1、利用BFC消除Margin Collapse

正常的情况下,一个容器内的所有盒子都会由上而下垂直排列(一个块级元素占一行)。而且,我们会发现,如果相邻的两个盒子都设置了margin属性,则margin属性并不会叠加(取垂直方向上叠加的两个margin分量的最大值),如:

<style type="text/css">
.box {  }
.box .s1 { height: 20px; background: #CCC; margin-bottom: 10px; }
.box .s2 { height: 20px; background: #CCC; margin-top: 10px; }
</style>
<div class="box">
    <div class="s1"></div>
    <div class="s2"></div>
</div>

那么,这种情况下,s1和s2两个DIV的间距并不会是我们期望的20px,而是只有10px
对于处在同一个BFC的元素来说,便会发生Margin Collapse现象,而处于不同的BFC的元素,就不会发生,所以,为了解决这个问题,我们需要的就是新建一个BFC,如:

<style type="text/css">
.box {  }
.box .s1 { height: 20px; background: #CCC; margin-bottom: 10px; }
.box .s2 { height: 20px; background: #CCC; margin-top: 10px; }
</style>
<div class="box">
    <div class="s1"></div>
    <div style="overflow:hidden">
        <div class="s2"></div>
    </div>
</div>

现在,s1和s2的间距是20px了

2、利用BFC容纳浮动元素

如果一个容器里包含有浮动元素,就有可能遭遇到容器高度为0的情况。如:

<style type="text/css">
.box { background: #000 }
.box .s1 { height: 20px; width: 100px; background: #CCC; float: left; }
.box .s2 { height: 20px; width: 100px; background: #CCC; float: left; }
</style>
<div class="box">
    <div class="s1">1</div>
    <div class="s2">2</div>
</div>

这种情况下,box的高度会是0。所以,为了解决这个问题,我们除了可以使用::after来添加clear:both外,还可以建立一个BFC,让它容纳浮动元素,如:.box { background: #000; overflow: hidden }

3、利用BFC阻止文本换行

在一般情况下,文本会围绕浮动元素。而有时候,我们不希望它围绕浮动元素,这种情况下,仍然可以利用BFC

因为浮动元素的移动,导致文本不得不移动来腾出位置。但是随着文本的增多,文本高度超过浮动元素的部分就不会在水平方向上挪出位置,所以便会导致看起来像是环绕。所以,这种情况下,我们为了实现figure2的效果,就可以用一个BFC包围文本,使得有一个统一的左边界,这样子的情况下,就不会再环绕浮动元素了,如:

<style type="text/css">
.box { width: 300px; }
.box img { width: 100px; float: left; }
.box p { overflow: hidden; }
</style>

<div class="box">
    <img src="pic.jpg" />
    <p>一大段文字,一大段文字,一大段文字,一大段文字,一大段文字,一大段文字,一大段文字,一大段文字,一大段文字,一大段文字,一大段文字,一大段文字,一大段文字,一大段文字</p>
</div>


参考资料

理解CSS中的BFC(块级可视化上下文)