在上文《详说清除浮动》中,Kayo 较为详细地介绍了 BFC ,也就是本文的主角 Block Formatting Contexts (块级格式化上下文),本文会基于上文关于 BFC 的部分进行拓展,进一步说明 BFC 的特性。html

但在进一步说明 BFC 特性以前,Kayo 首先要介绍另外一个在 CSS 的可视化格式模型 (Visual Formatting Model) 中具备很是重要地位的概念——定位方案。定位方案是控制元素的布局,在 CSS 2.1 中,有三种定位方案——普通流 (Normal Flow) 、浮动 (Floats) 和绝对定位 (Absolute Positioning) ,下面分别对这三种布局简略说明一下。浏览器

普通流(Normal Flow)ide

在普通流中,元素按照其在 HTML 中的前后位置至上而下布局,在这个过程当中,行内元素水平排列,直到当行被占满而后换行,块级元素则会被渲染为完整的一个新行, 除非另外指定,不然全部元素默认都是普通流定位,也能够说,普通流中元素的位置由该元素在 HTML 文档中的位置决定。布局

浮动 (Floats)post

在浮动布局中,元素首先按照普通流的位置出现,而后根据浮动的方向尽量的向左边或右边偏移,其效果与印刷排版中的文本环绕类似。google

绝对定位 (Absolute Positioning)orm

在绝对定位布局中,元素会总体脱离普通流,所以绝对定位元素不会对其兄弟元素形成影响(若是看了上文的童鞋,会发现这点与浮动元素会影响兄弟元素是不一样的),而元素具体的位置由绝对定位的坐标决定。htm

BFC 正是属于普通流的,所以它对兄弟元素也不会形成什么影响。开发

一. BFC 是什么?

有了上面的基础后,能够正式介绍 BFC 了。从样式上看,具备 BFC 的元素与普通的容器没有什么区别,可是从功能上,具备 BFC 的元素能够看做是隔离了的独立容器,容器里面的元素不会在布局上影响到外面的元素,而且 BFC 具备普通容器没有的一些特性,例如能够包含浮动元素,上文中的第二类清除浮动的方法(如 overflow 方法)就是触发了浮动元素的父元素的 BFC ,使到它能够包含浮动元素,从而防止出现高度塌陷的问题。rem

简单来讲,BFC 就是一种属性,这种属性会影响着元素的定位以及与其兄弟元素之间的相互做用。

二.如何触发 BFC

上面介绍了 BFC 的定义,那么如何触发 BFC 呢?

知足下面任一条件的元素,会触发为 BFC :

  • 浮动元素,float 除 none 之外的值
  • 绝对定位元素,position(absolute,fixed)
  • display 为如下其中之一的值 inline-blocks,table-cells,table-captions
  • overflow 除了 visible 之外的值(hidden,auto,scroll)

可是,"display:table" 自己并不产生 BFC,而是由它产生匿名框,匿名框中包含 "display:table-cell" 的框会产 BFC。 总之,对于 "display:table" 的元素,产生 BFC 的是匿名框而不是 "display:table"。

在 CSS3 中,BFC 叫作 Flow Root,并增长了一些触发条件:

  • display 的 table-caption 值
  • position 的 fixed 值,其实 fixed 是 absolute 的一个子类,所以在 CSS2.1 中使用这个值也会触发 BFC ,只是在 CSS3 中更加明确了这一点。

值得注意的是,在前面 Kayo 已经说明过了,BFC 并非元素,而是某些元素带有的一些属性,所以,是上面这些元素产生了 BFC ,而它们自己并非 BFC ,这个概念须要区分清楚。

三. BFC 的特性

从总体上看,BFC 是隔离了的容器,这个具体能够表现为三个特性:

1. BFC 会阻止外边距折叠

两个相连的 div 在垂直上的外边距会发生叠加,有些书籍会把这个状况列做 bug ,这里 Kayo 并不一样意,这种折叠虽然会给不熟悉 CSS 布局的开发者带来一些不便,但实际上它具备完整且具体的折叠规则,而且在主流浏览器中都存在,所以 Kayo 更认为这应该是 CSS 的特性。固然,在实际开发中,或许咱们有时会不须要这种折叠,这时能够利用 BFC 的其中一个特性——阻止外边距叠加。

在举例说明 BFC 如何阻止外边距折叠以前,首先说明一下外边距折叠的规则:仅当两个块级元素相邻而且在同一个块级格式化上下文时,它们垂直方向之间的外边距才会叠加。也就是说,即使两个块级元素相邻,但当它们不在同一个块级格式化上下文时它们的边距也不会折叠。所以,阻止外边距折叠只需产生新的 BFC 。

效果如图:

也能够看 Demo 。

如上图的例子,三个 div 各包含一个 p 元素,三个 div 及其包含的 p 元素都有顶部和底部的外边距,但只有第三个 div 的边距没有与它的子元素 p 的外边距折叠。这是由于第三个 div 建立了新的 BFC ,因而可知:建立了 BFC 的元素,不和它的子元素发生外边距折叠。

2. BFC 能够包含浮动的元素

这也正是使用 overflow: hidden 与 overflow: auto 方法闭合浮动的原理,使用 overflow: hidden 或 overflow: auto 触发浮动元素的父元素的 BFC 特性,从而能够包含浮动元素,闭合浮动。

W3C 的原文是“'Auto' heights for block formatting context roots”,也就是 BFC 会根据子元素的状况自动适应高度,即便其子元素中包括浮动元素。

效果如图:

也能够看 Demo 。

上面的例子中,有两个 div ,它们各包含一个设置了浮动的 p 元素,但第一个 div 出现了“高度塌陷”,这是由于内部的浮动元素脱离了普通流,所以该 div 至关于一个空标签,没有高度和宽度,即高度为 0 ,上下边框也重叠在一块儿。而第二个 div 使用 overflow: hidden 触发了 BFC ,能够包含浮动元素,所以能正确表现出高度,其边框位置也正常了。

3. BFC 能够阻止元素被浮动元素覆盖

如上文所说,浮动元素的块级兄弟元素会无视浮动元素的位置,尽可能占满一整行,这样就会被浮动元素覆盖,为该兄弟元素触发 BFC 后能够阻止这种状况的发生。

效果如图:

也能够看 Demo 。

如上图的例子,蓝色背景的 div 使用 overflow: hidden 触发了 BFC ,它并不会被它的兄弟浮动元素覆盖,而是处于它的旁边。值得注意的是,以上的状况仅仅是元素宽度之和没有超出父元素宽度的状况,假设浮动元素宽度和它的非浮动兄弟元素宽度都没有超过父元素宽度,但两个元素的宽度加起来超出了父元素宽度的时候,非浮动元素会降低到下一行,即处于浮动元素下方,效果以下图:

也能够看 Demo 。

四. BFC 与 hasLayout

细心的童鞋会发现,在上面的例子中,除了使用 overflow: hidden 触发 BFC 外,还使用了一个 *zomm: 1 的属性,这是 IEhack ,由于 IE6-7 并不支持 W3C 的 BFC ,而是使用私有属性 hasLayout 。从表现上来讲,hasLayout 跟 BFC 很类似,只是 hasLayout 自身存在不少问题,致使了 IE6-7 中一系列的 bug 。触发 hasLayout 的条件与触发 BFC 有些类似,具体状况 Kayo 会另写文章介绍。这里 Kayo 推荐为元素设置 IE 特有的 CSS 属性 zoom: 1 触发 hasLayout ,zoom 用于设置或检索元素的缩放比例,值为“1”即便用元素的实际尺寸,使用 zoom: 1 既能够触发 hasLayout 又不会对元素形成其余影响,相对来讲会更为方便。

这时咱们须要注意一个问题:既然 hasLayout 有着跟 BFC 类似的功能,那么在实际开发中,就要为须要触发 BFC 的元素同时触发 hasLayout ,这样 BFC 和 hasLayout 具备的一些特殊性质能够在现代浏览器和 IE 中同时产生,避免一个元素在不一样浏览器间的表现由于 BFC 或 hasLayout 出现差别。事实上,在实际开发中不少莫名其妙的问题其实都是所以而产生的。固然一样地,若是一个元素没有触发 BFC ,也要尽可能保证它没有触发 hasLayout 。

本文由 Kayo Lee 发表,本文连接:http://kayosite.com/block-formatting-contexts-in-detail.html