CSS进阶05-行内格式上下文IFC

1. IFC与line box

IFC的英文全称是:Inline Formatting Contexts,直译为“行内格式化上下文”。 IFC由一个不包含块级盒的块容器盒生成。 在行内格式化上下文中,盒从包含块的顶部开始一个接一个地水平摆放。盒水平方向的外边距、边框和内边距在布局时都会考虑在内。盒的垂直对齐方式则不一:可能按底部或者顶部对齐,又或者按它们内容文本的基线对齐。包含了形成一行的那些盒的矩形区域被称为行盒 Line Box 。

2. 行盒的高度

用户代理将行内级盒流入到一个行盒组成的垂直栈中。行盒的高度计算规则如下:

  1. 计算行盒内每个行内级盒的高度。对于替换元素replaced elements、行内块元素nline-block elements以及行内表格元素inline-table elements,高度是其margin box的高度;对于行内盒,高度是其 line-height。(参考 "Calculating heights and margins" 和 在 "Leading and half-leading"里的height of inline boxes)
  2. 行内级盒根据其 vertical-align 属性垂直对齐。如果它们对齐 top 或 bottom,它们必须对齐,以便使行盒高度最小化。如果这些盒足够高,则有多种解决方案并且CSS2.2没有规定此行盒的基线的位置(即,strut的位置,参见下文)。
  3. 行盒高度是最上盒顶部到最下盒底部的距离。(包括struct,解释参见下述 line-height。)

空的行内元素生成空的行内盒,但这些盒仍然有margins, padding, borders 和一个行高line height,因此跟有内容的元素一样会影响计算。

2.1 行距Leading和半行距half-leading

CSS假定每种字体都有字体指标,用于指定基线以上的特征高度和指定其下的深度。在本节中,我们使用A来表示高度(给定尺寸的给定字体)和D深度。我们还定义AD = A + D,即从顶部到底部的距离。(有关如何为TrueType和OpenType字体查找 A和D的说明,请参阅下面的注释)请注意,这些是整个字体的度量标准,不需要与任何单个字形的上行和下行对应。

用户代理必须通过其相关基线将非替换的行内框中的字形彼此对齐。然后,对于每个字形,确定A和D。需要注意的是在单个元素内的字形可能来自不同的字体,因此不需要都具有相同的A和D。如果行内盒完全不包含字形,则认为它包含了一个带有元素的首个可用字体的A和D的支柱(一个零宽度的不可见字形) 。

接着对每个字符添加行距L,其中 L = line-height - AD。行距的一般添加到A之上,另一半添加到D之下,从而赋予字符以及其行距一个基线之上的完整高度 A' = A + L/2,以及完整深度 D' = D+ L/2。 注:L可能为负。

包含了所有字符以及字符两侧半行距的行内盒的高度正是 line-height。子元素的盒不影响这个高度。

尽管非替换元素的margins, borders和padding不纳入行盒的计算,它们仍然渲染在行内盒的周围。这意味着如果 line-height 指定的高度小于被包含盒的content height,padding和borders的backgrounds和colors可能会渗透到相邻的行盒。用户代理应当按文档顺序渲染这些盒。这会造成后面的盒的borders会在前面盒的边框和文本上绘制。 注:CSS2.1没有定义什么是行内盒的内容区域(参见文档-10.6.1 ),因此不同的用户代理可能把backgrounds和borders绘制在不同地方。

注:推荐OpenType和TrueType字体(在转换到当前元素的字号后)的A和D使用该字体OS/2表格中的“sTypeAscender”和“sTypeDescender”特性。如果没有这些特性,则使用HHEA表中的“Ascent”和“Descent”特性。

2.2 行高属性line-height

line-height

在内容由行内级元素组成的块容器元素上,line-height 指定该元素内行盒的最小高度minimal height。最小高度由基线上方的最小高度和下方的最小深度组成,就如同每个行盒以一个具有该元素字体和行高属性的零宽度行内盒开始一样。我们称此虚构盒为“支柱 Strut ”。(该命名灵感源于Tex。)

字体在基线之上的高度和和基线之下的深度被假定为包含在字体内的特性。(更多细节,参见CSS3。)

在一个非替换行内元素上,line-height 指定一个高度用于计算行盒的高度。

line-height属性的值具有如下意义:

  • normal: 让用户代理设使用值为一个基于元素字体的“合理”值。该值与< number >意义相同。我们推荐 normal 的使用值在1.0到1.2之间。计算值为 normal。
  • < length > 指定长度用于计算行盒高度。负值非法。
  • < number > 属性的使用值为此数值乘以元素的字号。负值非法。计算值与指定值相同。
  • < percentage > 属性的计算值为此百分比乘以元素的字号计算值。负值非法。

下面例子中的三条规则的行高结果相同:

div { line-height: 1.2; font-size: 10pt }    /* number */
div { line-height: 1.2em; font-size: 10pt }    /* length */
div { line-height: 120%; font-size: 10pt }    /* percentage */

当元素包含以多种字体渲染的文本时,用户代理会根据最大字号来决定 normal 的 line-height 值。

注:如一个块容器盒中的所有行内盒仅有一个 line-height 值并且所有行内盒字体相同(并且行内盒中不存在替换元素、行内块元素等),上述将确保相邻行的基线正好相隔 line-height。这在不同字体的文本列必须对齐时非常重要,比如在table中。

2.3 垂直对齐属性vertical-align

vertival-align

此属性影响行内级元素生成的盒子在行盒内的垂直定位。

注:该属性值在表格上下文中有不同含义。请查阅table height algorithms一节了解详情。

下述值仅相对于 父行内元素(parent inline element) 或 父块容器元素的struct (the struct of a parent block container element)有意义。

在下述定义中,对行内非替换元素而言,用于对齐的盒是高度为 line-height 的盒(包括了盒的字形glyphs以及两侧的半行距half-leading,参见上面)。对于其他所有元素,用于对齐的盒是margin box。

  • baseline 将盒的基线与父盒的基线对齐。如果盒没有基线,将其bottom margin edge与父盒的 baseline 对齐。
  • middle 把盒的垂直中点同父盒的基线加上父盒一半的 x-height 对齐。
  • sub 把盒的基线降到父盒的下标的适当位置。(此值对元素文本的字号无影响。)
  • super 把盒的基线升到父盒的上标的适当位置。(此值对元素文本的字号无影响。)
  • text-top 把盒的顶部同父级的内容区域的顶部对齐(参见 10.6.1)。
  • text-bottom

把盒的底部同父级的内容区域的底部对齐(参见 10.6.1)。

  • < percentage > 把盒提升(正值)或降低(负值)指定距离(line-height 值的百分比)。值0% 意味着与 baseline 相同。
  • < length > 把盒提升(正值)或降低(负值)指定距离。值0cm 意味着与 baseline 相同。

下面的值使元素相对于行盒对齐。由于元素可能有子元素相对于该元素对齐(子元素又可能拥有后代相对于子元素对齐),因此下面的值使用对齐子树 aligned subtree 的边界。一个行内元素的对齐子树包括该元素以及 vertical-align 值不为 top 或 bottom 的所有子行内元素的所有对齐子树。该对齐子树的top是子树内最高的盒顶部,bottom也是类似这样。

  • top 把对齐子树的顶部与行盒顶部对齐。
  • bottom 把对齐子树的底部与行盒底部对齐。

行内表格inline-table的基线是表格首行的基线。

行内块的基线是其标准流内最后一个行盒的基线,除非该行内块没有 处于标准流内的行盒或者其 overflow 属性计算值不为 visible,这种情况下基线为bottom margin edge缘。

综合以上,行盒的高度总是足以容纳其包含的所有盒。然而,它可能高于其所包含的最高盒(例如,如果盒子是对齐的,以便基线对齐)。当一个盒子B的高度小于包含它的行盒的高度时, 行盒内 B 的垂直对齐方式由 vertical-align 属性决定。当在水平方向上几个行内级盒不能完全被单个行盒包含时,它们会被分配到两个或者多个垂直堆叠的行盒中。因此,一个段落就是多个行盒的垂直堆叠。行盒的堆叠没有垂直间距(除非有特别声明)并且从不重叠。

3. 行盒的宽度

一般来说,行盒的左边缘紧贴其包含块的左边缘,其右边缘紧贴包含块的右边缘。然而,浮动盒可能被置于包含块和行盒边缘之间。因此,尽管在同一行内格式化上下文中的行盒是等宽的(包含块的宽度),由于浮动会造成可用的水平空间减少,行盒的宽度仍可能变动。同一行内格式化上下文中的行盒在高度上通常是变动的(比如,一行可能包含图片但其他行仅包含文本)。

当一行中的行内级盒的总宽度小于包含它们的包含块的时候,它们在行里的水平分布取决于 text-align 属性。如果取 justify 值,用户代理可能拉伸行内盒( inline-table 和 inline-block 盒除外)中的空格和字间距。

当行内盒的宽度超过行盒宽度时,行内盒将被分为多个盒,被分解出的盒则又分布在多个行盒中。如果一个行内盒不可切割(比如,行内盒包含的是单个字符或者语言指定的断字规则不允许断字,又或者行内盒的 white-space 属性值为 nowrap 或 pre ),那么该行内盒将溢出行盒。

当行内盒被分割,外边距、边框和内边距在任何断点处都不会产生视觉影响。

行内盒也可能由于双向文本处理而在一个行盒内被切割成多个盒。

为了包含行内格式化上下文中的行内级内容,行盒按需创建。对于“不包含文本,没有保留的空白区域,没有margins、padding、border不为零的行内元素,也没有其他在标准流内 In-flow 内容(如图片、行内块或行内表格),并且不以保留的换行符结尾”的行盒,如果是为决定它们所包含的元素的定位,则必须视其为零高度的行盒,除此之外的其他目的下应视其为不存在。

下面是一个行内盒构造的例子。以下段落(由HTML块级元素 p 创建)包含了穿插有 em 和 strong 匿名文本。

<p>Several <em>emphasized words</em> appear
<strong>in this</strong> sentence, dear.</p>

p 元素生成了一个包含五个行内盒的块盒,其中三个行内盒是匿名的:

  • 匿名:"Several"
  • em:"emphasized words"
  • 匿名:"appear"
  • strong:"in this"
  • 匿名:"sentence, dear."

为了格式化该段落,客户端将五个行内盒放进若干行盒line boxes中。在这个例子中,由 p 元素生成的盒创建了这些行盒的包含块。

如果该包含块足够宽,所有的行内盒将放置在单个行盒中,如下:

包含块足够宽

如果宽度不够,行内盒就会被分割并分布在多个行盒中。段落可能就变成了:

包含块宽度变窄

或者:

包含块宽度更窄

在最后这个情况里, em 盒被分割成了两个 em 盒(现称之为 split1 和 split2 )。Margins, borders, padding, 或者 text decorations在 split1 之后或者 split2 之前都没有视觉效果。看如下示例:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
<title>Example of inline flow on several lines</title>
<style type="text/css">
   EM {
      padding: 2px; 
      margin: 1em;
      border-width: medium;
      border-style: dashed;
      line-height: 2.4em;
   }
</style>
</head>
<body>
<p>Several <em>emphasized words</em> appear here.</p>
</body>
</html>

根据 p 的宽度,这些盒可能按如下情况分布:

image.png

可以看到:

  • 外边距插在了 emphasized 之前和 words 之后
  • 内边距被插在了 emphasized 之前、上、下, words 值后、上、下。虚线边框渲染在了每个单词的三边。

就好像这个盒子在单行排好以后被直接掰开成两个一样。

参考

https://www.w3.org/TR/CSS22/visuren.html#visual-model-intro https://www.w3.org/TR/CSS2/visuren.html CSS规范 > 9 视觉格式化模型 Visual Formatting Model CSS规范 > 10 视觉格式化模型详述 Visual Formatting Model Details css中的IFC css中的bfc和ifc [译]:BFC与IFC 浅析css中的BFC、IFC、GFC和FFC css IFC 与 BFC分析

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏九彩拼盘的叨叨叨

SVG 直线路径写法示例

大写字母表示到后面值为绝对值,小写字母表示后面值为相对当前点的值 画一条起点是(10, 10)终点点是 (20, 30) 的线

10040
来自专栏cnblogs

深入理解和应用display属性(二)

四、inline-block 此类元素是inline + block的合体 1) margin和padding都有效;width和height都有效; .inl...

22060
来自专栏前端萌媛的成长之路

CSS选择器的优先级

18840
来自专栏从零开始学 Web 前端

从零开始学 Web 之 CSS(二)文本、标签、特性

当多个样式作用于同一个(同一类)标签时,样式发生了冲突,总是执行后边的代码(后边代码层叠前边的代码)。和标签调用选择器的顺序没有关系。

11360
来自专栏Jack的Android之旅

自定义天气显示温度变化的LinearChart控件

这次发表的是前几个月搞定的一个自定义控件,那时自己在写一个小的查看天气的软件,在这过程中就涉及了显示天气变化的折线图,一开始想用一些画图框架来解决问题,不过考虑...

29410
来自专栏web前端教室

20170108_先行者周日群视频课程——文字版

各位同学们大家好,又到周日了。因为1月1号是新年放假,所以今天也可以算是2017年的第一个周日,不知各位都对2017年有什么安排,而2016年又有哪些收获。我只...

21060
来自专栏移动开发

安卓属性动画小技巧

很多人第一次看到 view 的 getX getY 方法以为是取得相对于整个屏幕上的坐标,很容易在写一些动画效果出现不是预期的效果。

17040
来自专栏一个小程序员的成长笔记

CSS深入理解学习笔记之line-height

1、line-height的定义   定义:两行文字基线之间的距离。   注:不同字体之间的基线是不同的。 2、line-height与行内框盒子模型   行内...

33190
来自专栏程序你好

CSS盒子(Box)模型入门

无论您是CSS的新手还是经验丰富的老手,了解和理解box模型都很重要。让我们更好地了解它。

16820
来自专栏java小白

CSS三大特性

17140

扫码关注云+社区

领取腾讯云代金券