谈谈一些有趣的CSS题目(11)-- IFC、BFC、GFC 与 FFC 知多少

@chokcoco 2019-03-18 11:27:06发表于 chokcoco/iCSS 原理

11、IFC、BFC、GFC 与 FFC 知多少

这么多 *FC 都是些啥?

FC 即是 Formatting Contexts ,译作格式化上下文。 *FC 可以称作视觉格式化模型。CSS 视觉格式化模型(visual formatting model)是用来处理文档并将它显示在视觉媒体上的机制。这是 CSS 的一个基础概念。

比较常见的是 CSS2.1 规范中的 IFC(Inline Formatting Contexts)与 BFC(Block Formatting Contexts),至于后面两个,则是 CSS3 新增规范,GFC(GridLayout Formatting Contexts)以及 FFC(Flex Formatting Context)。

FC 是网页CSS视觉渲染的一部分,用于决定盒子模型的布局、其子元素将如何定位以及和其他元素的关系和相互作用。

理解各种 FC 背后的原理是掌握各类 CSS 布局的关键。

先了解几个概念,

Box

Box 是 CSS 布局的对象和基本单位,直观点说就是一个页面是由很多个 Box (即boxes)组成的,元素的类型和 display 属性决定了 Box 的类型。

  1. block-level Box:当元素的 CSS 属性 display 为 block, list-item 或 table 时,它是块级元素 block-level 。块级元素(比如<p>)视觉上呈现为块,竖直排列。
    每个块级元素至少生成一个块级盒(block-level Box)参与 BFC ,称为主要块级盒(principal block-level box)。一些元素,比如<li>,生成额外的盒来放置项目符号,不过多数元素只生成一个主要块级盒。

  2. Inline-level Box:当元素的 CSS 属性 display 的计算值为 inline, inline-block 或 inline-table 时,称它为行内级元素。视觉上它将内容与其它行内级元素排列为多行。典型的如段落内容,有文本或图片,都是行内级元素。
    行内级元素生成行内级盒(inline-level boxes),参与行内格式化上下文 IFC 。

  3. flex container:当元素的 CSS 属性 display 的计算值为 flex 或 inline-flex ,称它为弹性容器。
    display:flex这个值会导致一个元素生成一个块级(block-level)弹性容器框。
    display:inline-flex这个值会导致一个元素生成一个行内级(inline-level)弹性容器框。

  4. grid container:当元素的 CSS 属性 display 的计算值为 grid 或 inline-grid,称它为栅格容器。

栅格盒模型值,是一个仍处于实验中的属性。

块容器盒(block container box)

只包含其它块级盒,或生成一个行内格式化上下文(inline formatting context),只包含行内盒的叫做块容器盒子

也就是说,块容器盒要么只包含行内级盒,要么只包含块级盒。

块级盒(block-level Box)是描述元素跟它的父元素与兄弟元素之间的表现。

块容器盒(block container box)描述元素跟它的后代之间的影响。

块盒(BLock Boxes)

同时是块容器盒的块级盒称为块盒(block boxes)

顶住,概念真的很多。。。

行盒(Line boxes)

行盒由行内格式化上下文(inline formatting context)产生的盒,用于表示一行。在块盒里面,行盒从块盒一边排版到另一边。 当有浮动时, 行盒从左浮动的最右边排版到右浮动的最左边。

IFC(Inline Formatting Contexts)行内级格式化上下文

行内级格式化上下文用来规定行内级盒子的格式化规则。

先来看看如何生成一个 IFC :

IFC 只有在一个块级元素中仅包含内联级别元素时才会生成。

布局规则

  1. 内部的盒子会在水平方向,一个接一个地放置。

  2. 这些盒子垂直方向的起点从包含块盒子的顶部开始。

  3. 摆放这些盒子的时候,它们在水平方向上的 padding、border、margin 所占用的空间都会被考虑在内。

  4. 在垂直方向上,这些框可能会以不同形式来对齐(vertical-align):它们可能会使用底部或顶部对齐,也可能通过其内部的文本基线(baseline)对齐。

  5. 能把在一行上的框都完全包含进去的一个矩形区域,被称为该行的行框(line box)。行框的宽度是由包含块(containing box)和存在的浮动来决定。

  6. IFC中的 line box 一般左右边都贴紧其包含块,但是会因为float元素的存在发生变化。float 元素会位于IFC与与 line box 之间,使得 line box 宽度缩短。

  7. IFC 中的 line box 高度由 CSS 行高计算规则来确定,同个 IFC 下的多个 line box 高度可能会不同(比如一行包含了较高的图片,而另一行只有文本)

  8. 当 inline-level boxes 的总宽度少于包含它们的 line box 时,其水平渲染规则由 text-align 属性来确定,如果取值为 justify,那么浏览器会对 inline-boxes(注意不是inline-table 和 inline-block boxes)中的文字和空格做出拉伸。

  9. 当一个 inline box 超过 line box 的宽度时,它会被分割成多个boxes,这些 boxes 被分布在多个 line box 里。如果一个 inline box 不能被分割(比如只包含单个字符,或 word-breaking 机制被禁用,或该行内框受 white-space 属性值为 nowrap 或 pre 的影响),那么这个 inline box 将溢出这个 line box。

那么,IFC 的具体实用在何处呢?

  • 水平居中:当一个块要在环境中水平居中时,设置其为 inline-block 则会在外层产生 IFC,通过设置父容器 text-align:center 则可以使其水平居中。

值得注意的是,设置一个块为 inline-block ,以单个封闭块来参与外部的 IFC,而内部则生成了一个 BFC。

  • 垂直居中:创建一个IFC,用其中一个元素撑开父元素的高度,然后设置其 vertical-align:middle,其他行内元素则可以在此父元素下垂直居中。

使用 IFC 可以实现多行文本的水平垂直居中,可以看看下面这个例子:

Demo戳我:使用 IFC 可以实现多行文本的水平垂直居中

BFC(Block Formatting Contexts)块级格式化上下文

块格式化上下文(block formatting context) 是页面上的一个独立的渲染区域,容器里面的子元素不会在布局上影响到外面的元素。它是决定块盒子的布局及浮动元素相互影响的一个因素。

下列情况将创建一个块格式化上下文:

  1. 根元素或其它包含它的元素
  2. 浮动 (元素的 float 不为 none)
  3. 绝对定位元素 (元素的 position 为 absolute 或 fixed)
  4. 行内块 inline-blocks (元素的 display: inline-block)
  5. 表格单元格 (元素的 display: table-cell,HTML表格单元格默认属性)
  6. 表格标题 (元素的 display: table-caption, HTML表格标题默认属性)
  7. overflow 的值不为 visible的元素
  8. 弹性盒子 flex boxes (元素的 display: flex 或 inline-flex)

块格式化上下文包括了创建该上下文的元素的所有子元素,但不包括创建了新的块格式化上下文的子元素。

包含浮动元素的块塌缩,清除浮动等都是 BFC 的应用场景。

GFC(Grid Formatting Contexts)栅格格式化上下文

display:grid 篇幅巨大,建议看完大漠老师的教程:

CSS Grid布局

FFC(Flex Formatting Contexts)Flex格式化上下文

如上所述,当 display 的值为 flex 或 inline-flex 时,将生成弹性容器(Flex Containers)。

一个弹性容器为其内容建立了一个新的弹性格式化上下文环境(FFC)。

值得注意的是,弹性容器不是块容器,下列适用于块布局的属性不适用于弹性布局:

  1. 在CSS3多列布局模块中定义的 column-* 属性不适用于弹性容器。
  2. float 和 clear 属性对于弹性项没有作用,并不会把它带离文档流(或相反)。然而,浮动属性仍然会通过影响display属性的计算值而影响box的生成。
  3. vertical-align 属性对于弹性项没有作用
  4. ::first-line 和 ::first-letter 伪元素不适用于弹性容器,而且弹性容器不为他们的祖先提供第一个格式化的行或第一个字母。

看看下面的结构,

<div class="box">
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
</div>
.box{
  display: flex;
}

如上所示,采用 Flex 布局的元素,称为 Flex 容器(flex container),简称"容器"。弹性容器中的弹性项(flex item)表示其文档流(in-flow)内容中的框。

display:flex 篇幅巨大,建议看完下面两篇:

借用一句话:“’在工作过程中遇到某个属性的使用,浏览器渲染效果与预期效果不符,只能通过死记硬背能避免或应用这种效果,不知晓背后的原理,用就是这样的的借口来搪塞自己。”,所以对于布局问题,不要死记硬背,要去理解背后的各种原理。


最后,新开通的公众号求关注,形式希望是更短的篇幅,质量更高一些的技巧类文章,包括但不局限于 CSS:

image