重拾 CSS 之 BFC

2,664 阅读4分钟

BFC 为何物

格式化上下文(Block Formatting Context),是 Web 页面中盒模型布局的 CSS 渲染模式,主要指一个独立的渲染区域或一个隔离的独立容器。

需要什么条件(即如何脱离文档流)

  • 根元素(HTML元素),最大的一个BFC;
  • 浮动元素,floatnone 以外的值;
  • 定位元素,position: [absolute | fixed]
  • display: [inline-block | table-cell | table-caption]
  • overflow: [hidden | auto | scroll], 即除 visible 以外的值;

看例子

BFC 中的盒子对齐垂直存放

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>BFC 对齐</title>
    <style>
        * { margin: 0; padding: 0; }
        .absolute { position: absolute; }
        .left { float: left; }
        .section { width: 520px; }
        .section1 { background-color: red; min-height: 40px; }
        .section2 { background-color: orange; min-height: 40px; }
        .section3 { background-color: yellow; width: 100px; min-height: 40px; }
        .section4 { background-color: green;  min-height: 60px; }
    </style>
</head>

<body>
    <div class="section">
        <div class="section1">section1</div>
        <div class="section2">section2</div>
        <div class="section3 left">section3 float</div>
        <div class="section4">section4</div>
    </div>
</body>

</html>

哪怕浮动元素(section3)也接着上一个盒子垂直排列(所有的盒子都左对齐)。

外边距折叠

例子1

例子2

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>BFC margin</title>
    <style>
        * { margin: 0; padding: 0; }
        .hidden { overflow: hidden; }
        .section { margin: 20px auto; border:1px solid red; width: 800px; }
        .section1 { background-color: orange; margin: 10px; min-height: 40px; }
        .section2 { background-color: green; margin: 30px; min-height: 60px; }
    </style>
</head>

<body>
    <div class="section">
        <div class="section1"></div>
        <div class="section2"></div>
    </div>

    <div class="section">
        <div class="hidden">
            <div class="section1"></div>
        </div>
        <div class="section2"></div>
    </div>
</body>

</html>

例子1:两个内部盒子 section1section2 的垂直距离为 30px 而不是 40px,因为垂直外边距会折叠,间距以较大的为准;

例子2:如何解决垂直外边距不折叠呢?其实只要让 BFC 容器里的元素不会影响外面元素,同样外面元素不影响 BFC 容器里的元素,即让 section1section2 中一个盒子处于一个 BFC 容器中就行了;

不被浮动元素覆盖

例子1

例子2 和 例子3

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>BFC float</title>
    <style>
        * { margin: 0; padding: 0; }
        .hidden{ overflow: auto;}
        .left { float: left; }
        .right { float: right; }
        .section { margin: 20px auto; border: 1px solid red; width: 800px; }
        .section1 { background-color: orange; width: 100px; min-height: 40px; margin-right: 10px; }
        .section2 { min-height: 60px; background-color: green;}
        .section3 { background-color: pink; width: 100px; min-height: 40px;  margin-left: 10px; }
    </style>
</head>

<body>
    <div class="section">
        <div class="section1 left">
            <p>section1</p>
            <p>section1</p>
        </div>
        <div class="section2">
            <p>section2</p>
            <p>section2</p>
            <p>section2</p>
            <p>section2</p>
        </div>
    </div>

    <div class="section">
        <div class="section1 left">
            <p>section1</p>
            <p>section1</p>
        </div>
        <div class="section2 hidden">
            <p>section2</p>
            <p>section2</p>
            <p>section2</p>
            <p>section2</p>
        </div>
    </div>

    <div class="section">
        <div class="section1 left">
            <p>section1</p>
            <p>section1</p>
        </div>
        <div class="section3 right">
            <p>section3</p>
            <p>section3</p>
        </div>
        <div class="section2 hidden">
            <p>section2</p>
            <p>section2</p>
            <p>section2</p>
            <p>section2</p>
        </div>
    </div>
</body>

</html>
  • 例子1:字体环绕,浮动的盒子会遮盖下面的盒子,但是下面盒子里的文字是不会被遮盖的,文字反而还会环绕浮动的盒子(挺有有趣的),如何阻止文字环绕,可看例子2;
  • 例子2:两栏布局,左边固定宽度,右边不设宽(宽度自适应,随浏览器窗口大小的变化而变化);
  • 例子3:三栏布局,左右两边固定宽度,中间不设宽(宽度自适应,随浏览器的大小变化而变化);

BFC 包含浮动的块

其实就是清浮动(利用 overflow:hidden),可看面试之道之 CSS 布局

最后

总结下特征(能解决哪些问题)

  • 内部的 box 在垂直方向存放;
  • 垂直方向上的距离由 margin 决定(外间距之和);
  • BFC 的区域不会与 float 元素区域重叠(阻止文字环绕和实现多栏布局);
  • 计算 BFC 的高度时,浮动元素也参与计算(清浮动);
  • bfc 是页面上的一个独立容器,容器里的子元素不会影响外面元素;

本次代码 Github