CSS 中 block-level boxes、containing block、block formatting context 三者之间的区别和联系是怎样的?

关注者
181
被浏览
8804

4 个回答

这两天我又细看了一下 CSS 2.1 的关于 Visual formatting model 的内容 (w3.org/TR/CSS2/visuren.),并且画了一张里面提到的一些概念的关联图,是我边看边画的,结构没怎么安排有点乱,希望大家拍砖。


关于你说的几个概念:
  • block-level boxes
    一个 block-level element ('display' 属性值为 'block', 'list-item' 或是 ‘table’) 会生成一个 block-level box,这样的盒子会参与到 block-formatting context (一种布局的方式) 中。
  • block formatting context
    在这种布局方式下,盒子们自所在的 containing block 顶部起一个接一个垂直排列,水平方向上撑满整个宽度 (除非内部的盒子自己内部建立了新的 BFC)。
  • containing block
    一般来说,盒子本身就为其子孙建立了 containing block,用来计算内部盒子的位置、大小,而对内部的盒子,具体采用哪个 containing block 来计算,需要分情况来讨论:
    1. 根元素所在的 containing block 被称为 initial containing block,在我们常用的浏览器环境下,指的是原点与 canvas 重合,大小和 viewport 相同的矩形;
    2. 对于 position 为 static 或 relative 的元素,其 containing block 为祖先元素中最近的 block container box 的 content box (除 margin, border, padding 外的区域);
    3. 对于 position:fixed 的元素,其 containing block 由 viewport 建立;
    4. 对于 position:absolute 的元素,则是先找到其祖先元素中最近的 position 属性非 static 的元素,然后判断:
      1. 若此元素为 inline 元素,则 containing block 为能够包含这个元素生成的第一个和最后一个 inline box 的 padding box (除 margin, border 外的区域) 的最小矩形;
      2. 否则则由这个祖先元素的 padding box 构成。
      如果都找不到,则为 initial containing block。


基本就是规范上定义的,其中还涉及一些其他的概念,如果要了解的话可以继续阅读:
w3.org/TR/CSS2/visuren.
w3.org/TR/CSS2/visudet.

表格的布局的话比较特殊,另外研究吧。
想想浏览器怎么把一个元素“画”出来,至少要知道定位和尺寸。定位有三种normal flow, floats和absolute,无论属于哪种首先要找所在的containing block(我翻译为容器块),相当于一个大箱子里摆很多小盒子,小盒子怎么摆取决于大箱子。

怎么确定一个元素的containing block,由position属性确定:
1. static(默认的)/relative:简单说就是它的父元素的内容框(即去掉padding的部分)
2. absolute: 向上找最近的定位为absolute/relative的元素
3. fixed: 它的containing block一律为根元素(html/body),根元素也是initial containing block

block formatting context(块级格式化上下文)是一种布局特性,还是往箱子里放东西,bfc可以理解为打了"隔板"把一组小盒子分离开。

“block-level box一定会产生block formatting context”是错误的,block-level box须通过设置如overflow不为visible(IE6/7无效,可以设zoom)、float不为none等等来创建block formatting context。

触发了bfc的block level box,没有margin callapse的问题,并且边缘不会和float box的边缘重叠,利用它可以清浮动。

页面上任何一个元素都可以看成box,box分block-level,inline-level和匿名的。
为什么?