BFC 浅析

先前在学习CSS float时,有同学提到了BFC这个词,作为求知好问的好学生,哪里不懂查哪里,那么今天就来研究一下BFC究竟是什么。

BFC 是什么?

首先,BFC(block formatting context),中文直译:块格式化上下文。BFC的概念,无论是在W3C CSS2.1官方文档,还是在MDN文档中,都是十分难读懂的。再翻阅了大量博客后,首先必须了解,视觉格式化模型这个概念:

视觉格式化模型

CSS 视觉格式化模型(visual formatting model)是用来处理文档并将它显示在视觉媒体上的机制。这是 CSS 的一个基础概念。 视觉格式化模型根据 CSS 盒模型为文档的每个元素生成 0,1 或多个盒。

  • 盒尺寸:明确指定,受限或没有指定
  • 盒类型:行内(inline), 行内级别(inline-level), 原子行内级别(atomic inline-level), 块(block)盒;
  • 定位方案(positioning scheme): 常规流,浮动或绝对定位;
  • 树中的其它元素: 它的子代与同代;
  • 视口(viewport) 尺寸与位置;
  • 内含图片的固定尺寸;
  • 其它信息。

CSS 视觉格式化模型的一部分工作是从文档元素生成盒。生成的盒拥有不同类型,并对视觉格式化模型的处理产生影响。生成盒的类型取决于 CSS 属性 display

—— MDN - 视觉格式化模型

对于这个概念,可以简单理解为,页面文档在浏览器(视觉媒体)上的显示,是通过一定的模型构建的,就如同我们在word中写文章时,可以进行排版一样,这些模型就是帮助我们在浏览器中构建网页内容的排版。那么页面中的元素,就会根据这些模型生成一个个的盒子,这就是我们页面中的最基本的单位。

BFC基本描述

块格式化上下文(block formatting context) 是Web页面的可视CSS渲染的一部分。它是块盒子的布局发生及浮动体彼此交互的区域。

——MDN - 块格式化上下文

再看到MDN对于BFC的描述,可以理解为页面中的块盒(block boxes)所使用的的渲染模型就是BFC,当元素满足一定条件时,我们称之为触发了BFC,使其满足这个渲染模型的规范。

那么问题来了,什么是块盒(block boxes)?

块盒(block boxes)

块级元素与块盒(Block-level elements and block boxes)

当元素的 CSS 属性 displayblock, list-itemtable 时,它是块级元素 block-level 。块级元素(比如<p>)视觉上呈现为块,竖直排列。

块级盒参与(块格式化上下文 block formatting context)。每个块级元素至少生成一个块级盒,称为主要块级盒(principal block-level box)。一些元素,比如<li>,生成额外的盒来放置项目符号,不过多数元素只生成一个主要块级盒。

主要块级盒将包含后代元素生成的盒以及生成的内容。它也是可以使用(定位方案 positioning scheme)的盒。

Block boxes
Block boxes

一个块级盒可能也是一个块容器盒。块容器盒(block container box) 只包含其它块级盒,或生成一个行内格式化上下文(inline formatting context),由此只包含行内盒。注意块级盒与块容器盒概念不同。 前者描述元素跟它的父元素与兄弟元素之间的表现,后者描述元素跟它的后代之间的影响。有些块级盒,比如表格,不是块容器盒。相反,一些块容器盒,比如非替换行内块及非替换表格单元格,不是块级盒。

同时是块容器盒的块级盒称为块盒(block boxes)。(译注:块级盒与块盒名字相近,注意分别-

—— MDN - 视觉格式化模型

根据MDN文档,这里我整理了关于盒子的三个概念:

  1. Block-level boxes

    块级盒(Block-level boxes)指由块级元素构成的盒子,每个块级元素至少会生成一个盒子,我们称其为主块级盒子。块级盒描述块级元素跟它的父元素和兄弟元素的表现。

  2. Block containing boxes

    块容器盒(Block containing boxes)指只包含其他块级盒的盒子,或指生成行内格式化上下文(inline fomatting context)的盒子,由此生成的盒子只包含行内盒(inline boxes)。其描述了元素与后代之间的影响。

  3. Block boxes

    块盒(Block boxes)指既是块级盒,又是块容器盒的盒子。

总的来看,块盒属于一个复杂概念的集合,当一个盒子既包含块级盒又包含块级容器的概念时,它就是一个块盒。其中,包含了块级元素与父亲、兄弟、子代关系的描述和影响,还涉及了其他视觉格式化的内容。因此,BFC可以说是一种CSS 渲染的表现形式。

对于BFC,我们还需要了解其特性及触发条件:

BFC特性&创建条件

特性:

  1. 内部的Box会在垂直方向,从顶部开始一个接一个地放置。
  2. Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生叠加
  3. 每个元素的margin box的左边,与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
  4. BFC的区域不会与float box叠加。
  5. BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素,反之亦然。
  6. 计算BFC的高度时,浮动元素也参与计算。

——《CSS之BFC详解

创建条件:

块格式化上下文由以下之一创建:

  • 根元素或其它包含它的元素
  • 浮动 (元素的 float 不是 none)
  • 绝对定位的元素 (元素具有 positionabsolutefixed)
  • 内联块 inline-blocks (元素具有 display: inline-block)
  • 表格单元格 (元素具有 display: table-cell,HTML表格单元格默认属性)
  • 表格标题 (元素具有 display: table-caption, HTML表格标题默认属性)
  • 块元素具有overflow ,且值不是 visible
  • display:flow-root

——MDN - 块格式化上下文

BFC 可以用来做什么?

1. 解决margin重叠的问题

根据BFC的特性,同一个BFC下的两个相邻的盒子会出现垂直margin重叠的问题,这个问题会影响我们对页面布局的控制,通常我们可以为其中一个盒子添加一个父元素,并使其触发BFC,即可解决这个问题:

margin重叠

2. 浮动带来的布局问题

根据前面其他作者总结的BFC特性的第三条和第四条,我们知道在同一个BFC下即使有元素浮动,BFC下元素的最左边边缘总是会与包含它的盒子左边相接触,那么就会出现浮动元素遮盖了其他元素的情况。BFC还有一条重要特性:BFC的区域不会与float box 重叠。试想,在一个BFC,如果存在一个float元素,和一个div,浮动元素会遮盖住div,此时,如果给这个div构建一个新的BFC,由于BFC特性,内外不相互影响,此时div会被float元素挤开。

比如下面这个例子,绿色盒子会因为浮动遮盖住红色的盒子,但由于两个盒子都在同一个BFC(body元素)下,根据BFC特性,红色盒子会与包含块相接,此时只要让红色盒子触发BFC,我们为红色盒子添加一个触发BFC的条件overflow:hidden,此时红色盒子由于BFC的特性隔离开绿色,这样我们就可以通过float元素的方式实现两栏布局。

布局问题

3. 清除浮动

这里就要说到我们常见的浮动元素引起的高度坍塌的问题。由于浮动特性,浮动元素会脱离父元素,我们是否可以通过触发BFC来解决高度坍塌的问题呢?

根据特性的第6条,在触发BFC后,这个盒子的高度将包含浮动元素的高度,在计算时,浮动元素会参与高度计算,我们可以理解为,当一个父元素中包含了浮动元素,而浮动元素超出了父元素,此时我们为父元素创建BFC,那么浮动元素就会包裹进这个BFC解决了父元素中高度塌陷的问题。

如下面的例子,div.parent包含了两个div.child,而两个div由于赋予了float:left使其浮动,导致了div.parent高度的坍塌,此时我们给div.parent添加一个overflow:hidden属性值,使div.parent触发BFC,由于BFC下的盒子会包含浮动元素的高度,因此盒子就被撑了起来,高度塌陷的问题也就得到了解决。

清除浮动

除了上面的清除浮动用到了BFC的一些特性外,还有一些其他的清除浮动的技巧,这里就不再做深入讨论。

其他

在学习BFC过程中,主要借鉴了一些博客文章及MDN的说明,由于自己的书面表达能力有限,这篇文章主要用于记录学习BFC的过程,如有表述不清的地方还请见谅。

此外,为了补充疏漏的地方,增加W3C官方文档的阅读。不过官方文档中BFC及相关概念大多为描述,没有非常确切的定性,所以这里只放出来作为参考。由于自己的英语水平有限,如有描述不当的地方,请以W3C CSS官方文档为准。

BFC(block formatting context)的官方描述

我们来看看W3C CSS2.1文档中关于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.

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.

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).

简单的人肉+谷歌翻译:

浮动元素、绝对定位元素、块容器(比如 inline-blocks,table-cells,table-captions)及overflow值不为visable(除非该值已被传到视口)的块盒(block boxes),都会为其内容建立新的块格式化上下文(BFC)。

在一个BFC中,盒子将会垂直的从包含块(containing block)的顶部一个接一个的向下布置,兄弟元素之间的垂直距离将由margin属性确定。在BFC中,两个相邻的块级盒子(block-level boxes)之间的垂直边距(vertical margins)将会坍塌。

在一个BFC中,每个盒子的左外边缘会接触包容块的左边缘(对于从右往左的格式,则相反)。即便是在浮动floats情况下也是如此(尽管盒子的线框可能由于浮动而收缩),除非盒子建立了一个新的BFC(这种情况下,盒子自身可能会因为浮动变得更窄)。

格式化上下文(formatting context)

CSS 2.1 - 9.4 Normal flow

Boxes in the normal flow belong to a formatting context, which may be block or inline, but not both simultaneously.

Block-level boxes participate in a block formatting context. Inline-level boxes participate in an inline formatting context.

简单的人肉+谷歌翻译:

正常流中属于格式化上下文的盒子,可以是块或者内联,但不能同时存在。块级盒参与块级格式化上下文,行内级参与行级格式上下文。

包含块(containing block)

CSS 2.1 W3C 文档:

In CSS 2.1, many box positions and sizes are calculated with respect to the edges of a rectangular box called a containing block. In general, generated boxes act as containing blocks for descendant boxes; we say that a box "establishes" the containing block for its descendants. The phrase "a box's containing block" means "the containing block in which the box lives," not the one it generates.

Each box is given a position with respect to its containing block, but it is not confined by this containing block; it may overflow.

简单的人肉+谷歌翻译:

在 CSS2.1中,许多盒子的定位(positions)和尺寸(size)被用来计算相对于矩形盒子的边缘,这种矩形盒子我们称其为包容块(containing block)。通常,生成的盒子将作为后代盒子的包含块,我们称其一个盒子为其后代建立(establishes)包容块。“一个盒子的包容块(a box's containning block)“指”这个盒子所在的包容块“,而不是指这个盒子产生的块。

块级盒子(block-level boxes)

Block-level elements are those elements of the source document that are formatted visually as blocks (e.g., paragraphs). The following values of the 'display' property make an element block-level: 'block', 'list-item', and 'table'.

Block-level boxes are boxes that participate in a block formatting context. Each block-level element generates a principal block-level box that contains descendant boxes and generated content and is also the box involved in any positioning scheme. Some block-level elements may generate additional boxes in addition to the principal box: 'list-item' elements. These additional boxes are placed with respect to the principal box.

Except for table boxes, which are described in a later chapter, and replaced elements, a block-level box is also a block container box. A block container box either contains only block-level boxes or establishes an inline formatting context and thus contains only inline-level boxes. Not all block container boxes are block-level boxes: non-replaced inline blocks and non-replaced table cells are block containers but not block-level boxes. Block-level boxes that are also block containers are called block boxes.

The three terms "block-level box," "block container box," and "block box" are sometimes abbreviated as "block" where unambiguous.

简单的人肉+谷歌翻译:

块级元素是源文档中作为块被视觉格式化的元素(比如:paragraphs)。display属性作为元素块级的表示,其值有blocklist-itemtable

块级元素是参与BFC的盒子。每一个块级元素会生成一个主要块级元素盒(principal block-level box),盒中包含后代盒子和生成的内容,同时这个盒也包含任意定位方案。除了主块级元素盒外,一些块级元素也可能产生额外的盒子,比如:list-item元素。这些额外的盒子会被放置在相对主盒的地方。

除了后面章节描述的表格盒(table boxes)和替换元素外,块级元素盒(block-level box)同时也是一个块容器盒(block container box)。块容器盒要么只包块级盒,或建立内联格式化上下文(inline formatting)的情况下只包含内联级盒子(inline-level boxes)。并非所有块容器盒都是块级盒,不包含内联盒子和表单cell(table cell)的是块容器(block container),而不是块级盒(block-level boxes)。既是块级盒(block-level boxes)同时也是块容器(block container)的称为块盒(block boxes)。

块级盒(block-level block),块容器盒(block container box),块盒(block box)这三个术语有时会缩写为明确的:块(block)

参考:

  1. CSS之BFC详解
  2. W3C CSS2.1 spec 9 Visual formatting model
  3. 扒一下W3C规范里的BFC和IFC
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,165评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,720评论 1 298
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,849评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,245评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,596评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,747评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,977评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,708评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,448评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,657评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,141评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,493评论 3 258
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,153评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,108评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,890评论 0 198
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,799评论 2 277
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,685评论 2 272

推荐阅读更多精彩内容

  • 问答题47 /72 常见浏览器兼容性问题与解决方案? 参考答案 (1)浏览器兼容问题一:不同浏览器的标签默认的外补...
    _Yfling阅读 13,630评论 1 92
  • 什么是BFC BFC全称是Block Formatting Context,即块格式化上下文。它是CSS2.1规范...
    陌客百里阅读 527评论 3 4
  • 转载自(http://web.jobbole.com/83274/) BFC BFC全称是Block Format...
    居客侠阅读 2,096评论 0 20
  • BFC全称是Block Formatting Context,即块格式化上下文。它是CSS2.1规范定义的,关于C...
    xf0128阅读 303评论 0 0
  • 在普通流中的盒子会参与一种格式上下文,这个盒子可能是块盒也可能是行内盒,但不可能同时是块盒又是行内盒。块级盒参与块...
    出云月阅读 244评论 0 0