1. 1. 什么是BFC
  2. 2. BFC 规则概述
    1. 2.1. 如何创建BFC
    2. 2.2. BFC特性
    3. 2.3. BFC应用举例——多栏布局
      1. 2.3.1. 如何解决
Table of Contents

谈谈BFC

BFC牵扯了许多东西,能力时间有限,将逐渐补充先关内容。

什么是BFC

BFC(Block Formating Context)被称为块级格式化上下文。直白来讲,BFC只是一个概念,但凡符合这个定义的,便遵循BFC的渲染规则。

官网描述如下:

Floats, absolutely positioned elements, block containers (such as inline-blocks, table-cells, and table-captions) that are not block boxes, and block boxes with ‘overflow’ other than ‘visible’ (except when that value has been propagated to the viewport) establish new block formatting contexts for their contents.

也就是说,浮动、绝对定位元素(positionabsolutefixed)、行内块元素 display:inline-block、表格单元格 display:table-cell、表格标题 display:table-caption 以及 overflow 属性值不为 visible 的元素(除了该值被传播到视点 viewport 的情况)将创建一个新的块级格式化上下文。

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.

在BFC内,盒子从包含块(这个概念要清楚(⊙o⊙)哦)顶端开始,按垂直方向一个接一个排列。相邻两个盒子之间的垂直距离有margin决定,但并非简单的两个margin之和,而是采用所谓的外边距折叠(Collapsing Margins )

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中,每个盒子的左外边距紧贴包含块(对于从右往左的布局中,正好相反)。需要注意的是,即使是浮动元素,也遵循这个规则,除非我们为这个盒子新建了一个BFC。

BFC 规则概述

根据官方描述,对BFC触发条件以及渲染规则总结:

如何创建BFC

  1. 浮动:float不为none
  2. postion等于absolute或者flex
  3. display等于table-celltable-captioninline-blockflexinline-flex
  4. overflow不为visible

这几个条件各有利弊,结合具体情况灵活使用。

BFC特性

  1. 属于同一BFC的相邻元素会发生外边距折叠(换句话说,如果不属于同一个BFC,那就不会折叠了)
  2. BFC中的float元素会撑开容器
  3. 在BFC中,每个盒子的左外边距紧贴包含块

BFC应用举例——多栏布局

借用百度ife的一个任务:

效果图:

多栏布局
要求:改变中间一栏的内容长度,以确保在中间一栏较高和右边一栏较高时,父元素的高度始终为子元素中最高的高度

此题有多种优秀解决方案,在这我们关注如何利用BFC解决(这也是目前我认为此题最简单的解法)。

解题思路:

我们先让左侧和右侧站好位,剩下的空间给中间的模块。
左侧和右侧的两个盒子,那就直接采用float。但是有两个需要解决的地方:

  1. 一个元素浮动时,其他内容会“环绕”该元素。结果就是如果两个侧栏的高度小于中间栏,那中间栏就会环绕两个侧栏了。
  2. 浮动元素已经从文档的正常流中删除,存在高度塌陷。当左右侧栏的高度均大于中间栏的高度,父元素高度无法撑开。

如何解决

  • 避免环绕:首先要明白为何会存在“环绕”,原因在于,在BFC中,每个盒子的左外边距紧贴包含块的左侧。
    解决方法也很清楚了,让中间栏创建一个新的BFC就可以了。

  • 高度:上文说过,BFC可以包含浮动元素;所以只要为父元素创建BFC够了。

HTML代码

<div class="container">
        <div class="left-box">
            <img src="img/logo.jpeg" />
            <h2>九歌</h2>
        </div>
        <div class="right-box">
            <ul>
                <li><img src="img/qiu.jpeg" alt="秋"></li>
                <li><img src="img/rui.png" alt="瑞"></li>
                <li><img src="img/voya.jpeg" alt="运"></li>
            </ul>
        </div>
        <div class="center-box">
            <h2>关于我们</h2>
            <p>一张褪色的照片
好像带给我一点点怀念
巷尾老爷爷卖的热汤面
味道弥漫过旧旧的后院
流浪猫睡熟在摇晃秋千
夕阳照了一遍他咪着眼
那张同桌寄的明信片
安静的躺在课桌的里面
快要过完的春天
还有雕刻着图案的门帘
窄窄的长长的过道两边
老房子依然升起了炊烟
刚刚下完了小雨的季节
爸妈又一起走过的老街
记不得哪年的哪一天
很漫长又很短暂的岁月
现在已经回不去
</p>
        </div>
    </div>

CSS

.container{
    margin:20px;
    border: #999;
    background: #eeeeee;
    overflow: hidden;
    padding: 20px;
}

img{
    height: 80px;
    width: 80px;
}

.left-box,.center-box,.right-box{
    border: 1px solid #999;
    padding: 20px;
    background: #fff;
}

.left-box{
    float: left;

    width: 158px;
    margin-right: 20px;
}
.left-box img{
    float: left;
}
.left-box h2{
    overflow: hidden;
    padding-left: 20px;
}

.right-box{
    float: right;
    box-sizing: 120px;
    margin-left: 20px;

    text-align: center;
}

.center-box{
    overflow: hidden;
}