1. 引子

前两天在测试overflow:hidden属性,写了下面一个例子:

html<head>
<style type="text/css">
    #wrap{
        width:1000px;
        margin:0 auto;
        background-color:#FF0;
        height:200px;
        overflow:hidden;
    }
    #left{
        width:500px;
        height:400px;
        background-color:#FC8;
        float:left;
    }
</style>
</head>
<body>
    <div id="wrap">
        <div id="left"></div>
    </div>
</body>

你会发现效果是这样的。

这货是这样的

我比较不理解的是,#left 已经浮动了,脱离了常规流,为何 #wrap 这个外部盒子还能发挥 overflow:hidden 这个作用。

于是,谷歌一顿乱搜,发现了下面这个东西 Block Formatting Context块格式化上下文),CSS3 中也叫做 flow root。这玩意儿和引子中的问题好像没啥关系,但觉得挺有用的,还是写在下面。

2. 关于 BFC (flow root in CSS3)

我读了各种文章,列举比较好的几篇:

关于 BFC 或者 flow root 是啥,有啥特性,就不多解释了,上面那些文章解释得肯定比我要好。我说一下我从中的理解:

  • BFC 或者 flow root 是一个渲染的环境,与外部隔绝。不是随便一个 div 这样的块级元素就能触发的。它的触发需要一定的条件(那些文章中都有)。

下面这两点是不对的, BODY 并不会默认触发 BFC。 SF的Markdown编辑器好像没有删除线功能,就只能先这样表示了。当时不知道自己脑子抽风是怎么样想的。希望不要误导大家。后续会对这两点进行更正。也可参看 SF 中下面的这个问题,太牛啦。
问题

2. 一个 HTML Document 的 body 元素,默认触发了一个 BFC 或者是一个 flow root。(你可以在body里面写几个有边距的 div,看到边距重叠,就懂了。因为边距重叠是一个 BFC 或者 flow root 的特性。)
3. 基于第二点,不触发 BFC 或者不是一个 flow root 的普通块级元素,都在 '''body''' 这个 BFC 环境中。

  • 如果某个元素触发了 BFC 或者说成为了一个 flow root,那么这个元素将拥有新的一个 BFC环境(这使得这个元素和其兄弟元素、子元素之间的边距等效果会发生变化,具体详见上面文章的 BFC 特性。)

看了一圈下来,发现 BFC 确实可以解释很多问题,也有很多作用。如:

“'Auto' heights for block formatting context roots”
In addition, if the element has any floating descendants whose bottom margin edge is below the element's bottom content edge, then the height is increased to include those edges.

简单来说,就是若浮动的子元素的底部在外部元素之下,那么外部元素的高度将向下延伸,直至包裹这个浮动元素。(这也是外部容器盒中采用overflow:hidden来解决浮动带来的外部元素高度塌陷collapse的问题。这种方法也被叫做闭合浮动)。

3. 言归正传

BFC 或者 flow root 好像跟 overflow:hidden 能隐藏自身的浮动子元素溢出部分的关系不大。
原本以为隐藏溢出内容所在的子元素必须和父元素在一个流中,后来又去找了overflow:hidden隐藏溢出的资料,发现了

http://www.aliued.cn/2012/12/30/overflowhidden真的失效了吗.html

其中指出:

通常一个盒子的内容是被限制在盒子边界之内的。但有时也会产生溢出,即部分或全部内容跑到盒子边界之外。溢出将在满足下列条件之一时出现:
1. 一个不换行的行元素宽度超出了容器盒子宽度。
2. 一个宽度固定的块元素放在了比它窄的容器盒子内。
3. 一个元素的高度超出了容器盒子的高度。
4. 一个子孙元素,由负边距值引起的部分内容在盒子外部。
5. text-indent属性引起的行内元素在盒子的左右边界外。
6. 一个绝对定位的子孙元素,部分内容在盒子外。但超出的部分不是总会被剪裁。子孙元素的内容就不会被子孙元素和其包含块之间的祖先元素的overflow的设置所剪裁。

并且发现 position:absolute 的元素,也可以被隐藏溢出。
隐藏溢出跟是否在一个流中好像没什么关系...ORZ...
满足上述条件的,包括绝对定位和浮动,都可以被隐藏溢出。


本来是不想写这篇的,因为没啥结论得出来,还绕了个大圈。但就当做是对自己发现问题,解决问题的一种鞭策吧。继续加油!


Lemures
1.7k 声望23 粉丝

伪工科男。努力学前端中。