接下来将深入介绍 font-familyfont-sizeline-heightvertical-align 等。

文字

文字是通过文字制作软件做出来的,如 fontforge
制作文字时,有几根参考线。不同字体的参考线不同。

一般一共这 5 根参考线,不同的文字类型,这些参考线的距离会有所变化。

字体大小 font-size 设置的是文字的相对大小。
如活字印刷术:

字是刻在也正方型金属框内的,当金属框变大,字也应变大。
文字相对大小:1000、2048、1024等,无单位,表示相对大小(相当于金属框的大小)。
比如 Consolas 字体的相对大小是 2048(fontforge 软件):

当相对大小为2048时,顶线(Ascent)距离基线的距离是 1884,底线距基线的距离是514,所以顶线距底线的距离是 1884 + 514 = 2398 。

所以 Consolas 字体大小可记为 2398/2048 。


font-size

所以当给字体设置大小 font-size 为 200px 时,字体的实际大小是 200 * 2398/2048 ≈ 234px 。

<span>
    M
</span>
span{
    font-family: consolas;
    font-size: 200px;
}

文字顶线到底线的距离,是文字的实际大小(content-area,内容区)。行盒的背景,就覆盖这个 content-area。

span{
    background-color: aqua;
}

line-height

顶线向上延伸的空间,和底线向下延伸的空间,两个空间是相等的,该空间叫做 line gap,这个 gap 的大小默认是字体设计者决定的。

top 到 bottom 的距离,叫做 virtual-area,这个区域高度是可调的,即行高 line-height

line-height: normal 使用文字默认的 gap,

如 consolas 字体的默认 gap 是 0:

<p>
    <span>
    M
    </span>
</p>
p{
    background: red;
}
span{
    font-family: consolas;
    font-size: 200px;
    background-color: aqua;
}

而 Arial 字体的默认 gap 就不是 0:

span{
    font-family: Arial;
}

可以看到 <span> 的上下有一点红边,这个距离就是默认的 gap 了:

所以当把字体大小 font-size 和行高 line-height 同时设置为 200px 时(line-height 设置为 1 也一样),会出现这样的情况:

p{
    background: red;
}
span{
    background-color: aqua;
    font-family: consolas;
    font-size: 200px;
    line-height: 200px;
}

原因正如之前介绍的,font-size 设置的是相对大小,实际的字体大小是 234px,而行高 line-height 设置多少就是多少,也间接导致 gap 转化为了负数。

因而 line-height 设置为 1 (或者和字体大小相同)是一种不好的做法。

另外,视觉上大多文字是出现在行盒中间的,可实际上文字处于哪个位置是由文字设计者决定的。

比如小写字母 p,就处于行盒的下部分位置:

正确的说法是:content-area 出现在 virtual-area 的正中间。因为上下的 line gap 是一定相等的。

所以想实现所有字体的行高合适,使字与字上下之间 0 空隙贴合,是不可能的(除非你对于每一种字体的每一个大小都设置对应的行高)。

最合适的行高就是默认行高 line-height: normal 了。


vertical-align

通过上文,我们知道,参考线取决于 font-familyfont-sizeline-height

来回顾一下参考线的布局:

对于一个元素,如果其子元素出现行盒,该元素内部也会产生参考线。

<p>
    M
    <span class="test">
    M
    </span>
    <span style="background: gold;"> 
    M
    </span>
</p>

<span> 元素参考线确定后,<p> 元素也会产生参考线,这两组参考线默认情况下是基线对齐的(vertical-align: baseline):

p{  
    font-size: 100px;
    background: red;
}
.test{
    background-color: aqua;
    font-size: 150px;
    vertical-align: baseline;
}

可以清晰地看出,字母 M 的底部就是基线。

这种对齐的方式就是通过 vertical-align 来设置。

.test{
    vertical-align: super;
}

表示 <span> 元素的 基线 与其父元素 <p>上基线(super)对齐:

可以看到,这样一来,导致父元素 <p> 的基线位置变化,旁边那个黄色背景的 <span> 的位置也跟着变化了。

vertical-align: sub; 表示<span> 元素的 基线 与其父元素 <p>下基线(sub)对齐:

vertical-align: text-top; 表示 <span> 元素的 virtual-area 的顶边(top)与其父元素 <p>顶线(text-top)对齐:

virtual-area 的顶边是受行高 line-height 影响的。

vertical-align: text-bottom; 表示 <span> 元素的 virtual-area 的底边(bottom)与其父元素 <p>底线(text-bottom)对齐:

行盒组合起来可以形成很多行,每一行的区域就叫做 line-box(区分于行盒 inline-box),line-box 的顶边是该行内所有行盒中的最高顶边,底边是所有行盒中最低的底边。

line-box 是承载文字内容的必要条件,以下情况不生成 line-box:

  • 元素内部没有任何行盒
  • 元素内部字体大小为 0

vertical-align: top; 表示 <span> 元素的 virtual-area 的顶边(top)与 line-box 顶边 对齐;

vertical-align: bottom; 表示 <span> 元素的 virtual-area 的底边(top)与 line-box 底边 对齐;

vertical-align 取值为 数值 时表示相对于父元素基线的偏移量,可正可负。

vertical-align 取值为 百分值 时是相对于自身的 virtual-area 高度百分比,对于父元素基线的偏移量,也可正可负。

vertical-align: middle; 表示 <span> 元素的 基线(top)与 X 字母高度的一半位置 对齐;


可替换元素盒行块盒的基线

可替换元素,如图片 <img>,它的基线位于图片的下外边距。

所以这就解释了之前提到的图片底部白边的问题,是因为图片的基线与其父元素基线对齐导致的。

表单元素,基线位置在内容的底边位置。

行块盒

  • 有文字时,最后一行有 line-box,用最后一行的基线作为整个行块盒的基线
  • 没有文字时,基线位置在下外边距