1. IFC与line box
IFC的英文全称是:Inline Formatting Contexts,直译为“行内格式化上下文”。
IFC由一个不包含块级盒的块容器盒生成。
在行内格式化上下文中,盒从包含块的顶部开始一个接一个地水平摆放。盒水平方向的外边距、边框和内边距在布局时都会考虑在内。盒的垂直对齐方式则不一:可能按底部或者顶部对齐,又或者按它们内容文本的基线对齐。包含了形成一行的那些盒的矩形区域被称为行盒 Line Box 。
2. 行盒的高度
用户代理将行内级盒流入到一个行盒组成的垂直栈中。行盒的高度计算规则如下:
计算行盒内每个行内级盒的高度。对于替换元素replaced elements、行内块元素nline-block elements以及行内表格元素inline-table elements,高度是其margin box的高度;对于行内盒,高度是其 line-height。(参考 "Calculating heights and margins" 和 在 "Leading and half-leading"里的height of inline boxes)
行内级盒根据其 vertical-align 属性垂直对齐。如果它们对齐 top 或 bottom,它们必须对齐,以便使行盒高度最小化。如果这些盒足够高,则有多种解决方案并且CSS2.2没有规定此行盒的基线的位置(即,strut的位置,参见下文)。
行盒高度是最上盒顶部到最下盒底部的距离。(包括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 指定该元素内行盒的最小高度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
此属性影响行内级元素生成的盒子在行盒内的垂直定位。
注:该属性值在表格上下文中有不同含义。请查阅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 的宽度,这些盒可能按如下情况分布:
可以看到:
- 外边距插在了 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分析