字号大小实际上对应什么?

30

我正在尝试找出在font-sizeCSS属性中设置的值所对应的内容。

为了提供上下文,我想在CSS中获取字体部分(大写高度以上和基线以下)的em大小,我根据其OS / 2指标知道。 em单位是相对于给定的font-size的,而OS / 2指标则是相对于em square的。

我的期望

我的期望基于以下参考资料。 我没有发现更清晰或精确的信息。

  1. 根据CSS2.1中font-size的W3C参考,并在我在所有Stack Overflow问题中找到的主题(这里这里这里)中引用:

    字号对应于em square,这是排版中使用的概念。请注意,某些字形可能会超出其em square。

  2. 根据我在排版方面拥有的一些知识,em square是整个字体度量的方形,其中定义了上升、下降、间隙(等等...)行。 在OS / 2度量中,em square是字体本身的大小(通常为1000或2048UPM)。

    Letter metrics
    (来源:microsoft.com

    我从W3C中找到的唯一解释在CSS1的旧参考资料中,它与我使用的现代数字定义的em square一致:

    某些值(如宽度度量)以相对于抽象正方形的单位表示,该正方形的高度是相同字号类型之间的行距。这个正方形被称为EM square。 (...) 常见的值为250(Intellifont),1000(Type 1)和2048(TrueType)。

因此,如果我正确理解这些参考资料,则应使用font-size中指定的值来生成字体的整个em square,并且我们应该能够从字体的大小和度量计算出字体的一部分大小。

例如,使用...

.my-letter {
    font-family: 'Helvetica Neue';
    font-size: 100px;
    text-transform: uppercase;
}

......我们应该有一个em方块100px,因为Helvetica Neue的大写字母高度为714 / 1000(OS/2表中的sCapHeight),大写字母的高度为71.4px

期望字母

实际发生了什么。

生成的em方块font-size更大(在Mac上的最新版本的Chrome、Firefox和Safari上测试过)。起初,我以为浏览器对em方块有另一种定义,并且使得字母的某个部分等于font-size,但我没有找到任何与之匹配的OS/2度量(带或不带上升值,下降值,间隙等...)。

渲染字母

您也可以查看此CodePen。请注意,我使用line-height: 1;来突出显示预期的大小,但我的问题是关于font-size("渲染油墨")而不是line-height("碰撞框")。这是我必须明确的,因为我已经被误解了多次。line-height不是问题


所以我有三个问题:

  • 我是否正确理解了W3C的参考资料,或者我正在假设这些参考资料没有说的事情?
  • 如果没有,为什么生成的字体具有比font-size更大的em方块?
  • 最重要的是:我如何知道渲染的em方块的大小(相对于font-size)?

感谢您的帮助。


1
相关链接:https://dev59.com/wbPma4cB1Zd3GeqPt6a5 - Temani Afif
1
在graphicdesign.stackexchange.com上有一个有趣的(非CSS特定,但仍然相关的)问题:字体大小确切地转换为什么? - bluenote10
2个回答

9
你对W3C参考文献的理解是正确的,但你对红色框的理解是不正确的。
红色框不描绘em方块。它的高度是来自度量值中上升和下降的总和。

你是正确的。这意味着:1:上升和下降超出了em方块。2:x高度和大写字母高度实际上没有改变。3:我可以推断碰撞框顶部/底部与大写字母顶部/基线之间的距离。4:在字体中(至少对于Helvetica Neue),我无法使用任何指标来知道真正的上升(例如小写字母'l'或'h'的顶部)。我是正确的吗? - ncoden
@ncoden - 多多少少是的。上升和下降与em方格是独立的。也就是说,对于任何给定的字体,它们的总和可能大于、等于或小于em方格,因此它们不一定是“超出”em方格,尽管似乎常见的情况是它们的总和大于em方格。 - Alohci
值得注意的是,尽管字体度量包含上升线、下降线和大写字母高度,但单个字形不一定遵守这些度量标准——例如,实际的大写字母"A"可能比大写字母高度更高或更矮,而小写字母"o"的最低点可能会在基线上方或下方绘制。 - Alohci
1
我在这里找到了更多信息。是的,每个字母都有自己的上升部分和下降部分,但TypoAscenderTypoDescender指标旨在成为可用于字符行的“全局”上升/下降值。但对于Helvetica Neue和其他一些字体,这些指标等于WinAscender和WinDescender,并描述了“最大”的上升/下降值。 - ncoden

2

这篇文章(曾在已删除的答案中分享)解释得非常清楚。这是我尝试将其转化为一个独立的答案。

假设我们有一个使用font-family: Robotofont-size: 48px样式的<span>,我们想回答一个看似简单的问题:这个标签的有效高度是多少?答案是65px。以下是如何推导出来的:

首先,您需要了解一些关于字体的指标。如果您使用Linux,可以像这样使用FontForge检查字体:

$ fc-list | grep Roboto
$ fontforge /usr/share/fonts/truetype/roboto/hinted/Roboto-Regular.ttf

在“元素 => 字体信息... => 通用”下,您可以获取“Em Size”,它类似于字体的无单位基本单位:

enter image description here

在“元素 => 字体信息... => OS/2 => 指标”下,您可以找到上升/下降,这是字体的最大扩展:

enter image description here

浏览器所做的是将 em 大小 (2048) 与指定的字体大小 (48px) 进行匹配。基于此,它计算出上升/下降区域(2146,-555)相对于 em 大小的大小。因此,公式大致为:
result_size = (ascent + |descent|) / em_size * font_size

在这个例子中:
(2146 + 555) / 2048 * 48px = 63.375px

剩下的问题是为什么浏览器最终实际上会到达65像素。我的假设是上升和下降分别向上舍入。单独应用公式得到50.30像素 => 51像素的上升和13.01像素 => 14像素的下降,最终结果恰好为65像素。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接