关键词
盒子模型(box model) 行盒(line box) 行内盒(inline boxes) 行高(line-height)
行内元素的垂直对齐(vertical-align) font-size font-family 字体度量
前言:
关于行内元素的视觉表现涉及到了很多 CSS 方面的术语,比如:行框,行盒,在不同的书或博客中有使用行框的,有使用行盒的,那么对于刚接触这些概念的我们,往往会有疑问,它们有什么区别?其实是没有区别的,这是由于译者不同的用词习惯导致的,所以今后学习这些新知识有能力最好还是阅读英文文档
译者注:由于不同志愿者的用词习惯,box有时候被翻译成“盒子”,有时候被翻译成“框”。又由于一篇文章有时候由好几位志愿者共同翻译,因此常常在一篇文章中既出现了“盒子”,又出现了“框”,这给读者造成了很大的困扰。在之前几个模块的本地化工作时,我个人认为“框”能更准确表达出box的意思。在W3C上,那里的译者也将box翻译成“框”。但是显然的,“盒子”比“框”更容易区分——“框”容易和“边框(border)”混淆。我在这里特地增加了一个译者注,是希望读者在之后的阅读中能够明白“框”=“盒子”=box,边框=“border”。诸如此类的,padding大部分人翻译成“内边距”,但是padding也有人翻译为“填充”。
来源于 MDN
行盒内元素的排版
IFC布局规律
- 在一个行内格式化上下文中,盒是一个接一个水平放置的,从包含块的顶部开始
- 这些盒之间的水平
margin
,border
和padding
都有效 - 盒可能以不同的方式竖直对齐:以它们的底部或者顶部对齐,或者以它们里面的文本的基线对齐
什么是行盒(line box) 以及行盒的形成
包含来自同一行的盒的矩形区域叫做行盒(line box)也叫行框.
line box
的高度总是足以容纳它所包含的所有行内框(也叫内联盒子或叫行内盒), 即该行中出现的内联盒子的最高点和最低点的最小框.
换句话说, 行盒的上边界要位于最高内联盒子的上边界, 而行盒的底边要放在最低内联盒子的下边界
line box
的宽度由包含块和float
情况决定,一般来说,line box
的宽度等于包含块两边之间的宽度,然而float
可以插入到包含块和行盒边之间,如果有float
,那么line box
的宽度会比没有float
时小
特点:
每一行都是一个行盒, 同一段文本从一行变成多行, 行盒的个数也会发生变化.
行盒模型(line box)和行内元素的盒模型(inline box)不是一个东西, 行盒模型这个盒子实际是看不到的, 他仅仅是由一行行内元素所确定的这么一个东西.
,但不总是等于某个最高的行内元素的line box
的高度由line-height
决定line-height
, 因为行内元素的vertical-align
会影响行内元素的对齐方式而导致最高的行内盒子的底部不一定是 line box 的底部,如上图.
|
|
line box
之间的高度各不相同(比如只含文本的line box
高度与包含图片的line box
高度之间)行盒的高度是根据子元素的高度来计算,注意这里子元素的高度并不是子元素内容区域(content-area)的高度,这是有很大区别的.
尽管这听起来可能有些奇怪,行内元素有两个不同高度:
content-area
(内容区域)高度和virtual-area
(虚拟区域)高度(这是我发明的术语virtual-area高度,你在规范中是找不到任何相关的内容).content-area
高度是由font-family
,font-size
来决定的.virtual-area
高度是line-height
,它的高度用于计算line-box
的高度.只是计算,并不等于
- 当一行的行内级盒的总宽度小于它们所在的
line box
的宽度时,它们在行盒里的水平分布由text-align
属性决定。如果该属性值为justify
,用户代理可能会拉伸行内盒(不包括inline-table
和inline-block
盒)里的空白和字(间距)
行内盒(inline box)
一个
inline box
是一个(特殊的)行内级盒,其内容参与了它的包含行内格式化上下文当一个
inline box
超出一个line box
的宽度时,它会被分成几个盒,并且这些盒会跨多line box
分布。如果一个inline-block
无法分割(例如,如果该inline box
含有一个单个字符,或者特定语言的单词分隔规则不允许在该inline box
里分隔,或如果该inline box
受到了一个值为nowrap
或者pre
的white-space
的影响),那么该inline box
会从line box
溢出当一个
inline box
被分割后,margin
,border
和padding
在发生分割的地方(或者在任何分割处,如果有多处的话)不会有可视化效果同一个
line box
里的inline box
也可能因为双向(bidirectional)文本处理而被分割成几个盒
1.盒子的生成
inline 元素(span, 图片, 文字…)生成各种 inline boxes, 其内容参与了它的包含行内格式化上下文
2.盒子的高度计算(line-height登场)
包括行内非替换元素和行内替换元素的高度计算
3.盒子的摆放(vertical-align登场)
3.1 当设置 vertical-align 属性的时候,谁和谁对齐?对于行盒的 baseline 如何确认?
该属性会影响由一个行内级元素生成的盒的行盒内部的竖直定位
默认情况下,inline
,inline-block
以及table-cell
可以应用vertical-align
3.1.1 这里反复提到父级盒的基线,那么这个父级盒是指 包含块元素 还是 行盒?
3.1.1.1 如果父级盒是指块级盒
对于包含块,即使没有显示地设置字体属性,它也是有自己的字体的(默认是serif
),字体有了那么它的基线位置就确认了,line-height 有了,那么这个字体的内容形成的一个匿名inline box
的高度也就有了,那么line box
内所有inline box
的参照物也就有了
3.1.1.2 如果父级盒是指行盒
(《CSS 权威指南》195页中父级盒就是指行盒),这里父级盒如果是指line box
,困扰自己最大的问题是:一个行框内有多个行内框的时, 行框的基线如何确定?
注意
vertical-align:middle属性的表现与否,仅仅与其父标签有关,至于我们通常看到的与后面的文字垂直居中显示那都是假象!
如何理解:因为改变图片的vertical-align
属性以后,图片位置会上移或下移,而文字在那里却纹丝不动!,这说明什么?说明vertical-align: middle
带来的图文对齐效果是顺带的,与后面的行内水平的元素不存在直接关系,具体地分析见张鑫旭老师的 vertical-align 属性是如何起作用的
3.2 没有基线的inline box 如何对齐?
比如对于行内替换元素img
对于 行内替换元素(比如img)的基线就是其margin底边缘
对于
inline- block
元素比较复杂:一个inline- block
元素,如果里面没有inline
内联元素,或者overflow
不是visible
,则该元素的基线就是其margin底边缘,否则,其基线就是元素里面最后一行内联元素的基线,具体地看张鑫旭老师的 inline-block和baseline
4.行盒的确立(定行高)
可以通过这个过程来了解一行的各部分如何共同确定其高度
确定行中各
inline box
的高度(注意:inline box
的高度 ≠ 内容区域的高度)对于可替换元素(比如
img
,svg
,input
),inline-block
元素和inline-table
元素占据的高度(即inline box
高度) ,这个值就是其margin box
的高度,如果hegiht
的值是auto,然后使用line-height
时content-area
严格上等于line-height
.对于非替换元素
inline box
占据的高度不由行高决定,而是内容区域和行间距,只不过,正好content area + vertical spacing = line-height
,所以我们就可以认为行高就是非替换元素形成的inline box
的高度,就像欧姆定律可以计算出电阻,但不能说电压和电流决定了电阻.内容区域(content area)
是一种围绕文字看不见的盒子.content-area
和font-size
以及font-family
相关, 和line-height
没有任何关系关于
em盒子
也叫 em 框 模型,其实就是字体的容器,这个属于content-area
,这也是为什么算content-area
的时候即使不算vertical spacing
(行间距),文字仍然有上下左右留白的原因.
如果 line-height 没有指定值,如何计算?
没有指定值的 line-height 是有默认值的,默认值为 normal
,而 normal 在不同的浏览器,不同字体下的值是不同的.为了计算出 line-height 的具体值, 我们需要知道 normal 对应的值,然后乘以 font-size 即可求出行内元素的行高.
normal 的计算:
- 设置字体的 font-size 为100px, 方便计算
- 通过 Chrome 的检查工具获取行内元素的高度,此时因为行内没有别的 font-family 的元素,所以
vertical spacing 为0
,即 行内元素的高度表现 =content-area
=line-height
- 高度 / font-size = 该字体normal 值对应的数值
补充
vertical spacing
的值可大可小,还可以为负,它的作用只是保证行内盒子的高度正好等同于行高
2.确定替换元素的高度
- 得到各替换元素的 height margin-top margin-bottom padding-top padding-bottom border-top-width border-bottom-width的值,把它们加起来
3.取该行内最高盒子的ine-height形成高度
3.line box的高度等于最高inline box
的上边界加上最低inline box
的下边界,或者说是 父级盒基线的位置到最高inline box
的上边界的距离加上父级盒基线的位置到最低inline box
的下边界的距离.
3.通过行高定基线,基线确定别的线
对于各内容区,确定它在整行基线的上方和下方分别超出多少.这个任务并不容易:你必须知道各元素及匿名文本各部分的基线的位置,然后让它对齐该行基线.另外,对于替换元素,要将其底边放在整行的基线上
《CSS 权威指南》
注意:这段是根据父级盒指行盒产生的理解.即先定行盒的基线再摆放元素,但是这有一个最大的问题,盒子未摆放之前,行盒根本无法确立,所以删掉了这段
4.vertical-align 修饰细节
注意:这段和上一段是一起的,即确立行盒=>确立行盒的基线=>盒子根据默认的对齐方式对齐=>vertical-align
进行细节修饰,但是这也存在上面一样的问题:盒子未摆放之前,行盒根本无法确立.并且修改vertical-align
会影响行盒的高度,行盒被修改了,那么行盒的基线肯定发生变化造成循环影响,所以删除掉了这段
对于指定了 vertical-align值的元素,确定其垂直偏移量,由此可知该元素的内联盒子要向上或向下移多远,并改变元素在基线上方或下方超出的距离
5.计算多行文本的高度
所有line boxes 的行高加起来,即为行内元素的高度表现.
5.1 结论
所以一个没有设置height属性的包含块高度就是由一个一个line boxes的高度堆积而成的。
6.影响 line box 高度的因素
line-height
通过影响inline box
的高度影响line box
的高度不同的
font-family
的文字通过baseline
位置的不同,影响盒子的对齐而会影响line box
的高度font-size
通过影响数值单位的line-height
影响line box
的高度vertical-align
影响inline box
的对齐方式,影响line box
的高度特别注意的是, 设置
inline
元素的垂直距离无法改变行盒的高度, 视觉表现为文字还待在该待的地方,即垂直方向上的margin、padding、border是不占据空间的,但是唯一和块元素表现相同的是margin还是透明色,padding、border还是能够显示背景色的。同时由于对html文档的渲染是从上到下的,所以可能存在后面的行内元素的垂直方向的背景色覆盖前面的元素,对后面的元素中文字部分不会覆盖。
6.1 line-box计算的小细节:
对于行内非替换元素,padding和border增加了其background区域,但不会增加内容区域高度(甚至是line-box高度)。因此,你在屏幕上看到的不一定就是内容区域。margin-top 和 margin-bottom 对内联元素不生效。
对于行内替换元素,
inline-block
和blocksified
行内元素,padding
,margin
和border
都会增加高度,所以内容区域和line-box
的高度也会增加
7.补充
由于以上例子中使用到的字体可能在用户的系统里并不存在,然后发现设置不同的font-family
失败,可以参考:
更多关于CSS来控制字度的度量指标的问题,请参考大漠老师翻译的深入了解CSS字体度量,行高和vertical-align
下面来看几个实际开发中遇到的问题
图文混排
|
|
信息:
- 包含块不设置高度
- inline 元素嵌套并不会让 inline 盒子嵌套
line box
内包含 替换元素(img),不同font-size
和line-height
的inline box
- 默认的
vertical-align
- 对于不可替换的行内元素,width和height这两个属性是不能描述一个不可替代的行内元素的,所以说一直都是默认值auto.

图文混排的包含块高度
行内元素在盒模型中的表现:
按照盒子的生成=>盒子的高度计算=>盒子的摆放=>行盒的确立
包含块高度112px,行高100px, 说明
line box
的高度不等于line box
内最高inline box
的高度,并且line box的高度并不由line-height
决定112的由来:包含块2px 的 border,以及
line box
的高度,其中上边界是 img元素的 margin-top,下边界是.a
的inline box的 bottom
2. 不同 font-family 的 inline box 高度表现
|
|
信息:
- 包含块盒子不设置高度
- 默认的 line-height
- 相同的 font-size
- 默认的 vertical-align
可以发现包含块的高度为164px,刚好是font-family: Catamaran
的inline box
的content-area
,(在不指定行高的情况下,content-area 等于 line-height 的值,而在不指定竖直方向的padding,border的情况下,通过 Chrome 面板获取的元素占据尺寸就是 content-area的值,如图)

包含块不设置高度时的高度表现

不设置竖直方向的 padding,border 实元素的占据尺寸
带 padding 和 border的元素的占据尺寸