天天看点

CSS自定义字体 竖向偏移怎么办?聊聊字体文件的字体度量、上升、下降

背景

昨天我发布了联机象棋《联机象棋发布!打开URL就能联机对战!观战!单机演练!分享残局!》,有玩家试玩,截图如下:

CSS自定义字体 竖向偏移怎么办?聊聊字体文件的字体度量、上升、下降

通过截图大小以及里面的emoji我推断出:这是一台Windows PC。

之前我在Android、iOS、MacOS上都测试过,表现正常,唯独没有测试Windows,结果真的出问题了。那就尝试修复下吧!

现状

我是用SVG展示的文字,并且用了自定义字体。我使用React开发的,下面是JSX语法:

<g>
  <use xlinkHref="#piece-red" x={x} y={y}
  <text className="piece-text" x={x} y={y} fontSize="5" fill="white" textAnchor="middle" alignmentBaseline="central">{text}</text>      

其中​

​use​

​​就是棋子的圆圈⭕️,没有字的那种,​

​text​

​就是文字。

我给他们设置了一样的的x和y,棋子圆圈的x和y就是圆心的坐标,文字的x和y通过​

​textAnchor="middle" alignmentBaseline="central"​

​保证它垂直水平中心位于x、y处。这样文字就一定处于棋子圆圈中心了,而不需要我人肉计算坐标,比较方便。效果如图:

CSS自定义字体 竖向偏移怎么办?聊聊字体文件的字体度量、上升、下降

另外,值得一提的是,由于不是所有设备都安装了隶书字体,我使用了自定义的字体,保证了多个设备的UI统一,并且由于字体文件非常小,只有6kb,所以体验也很好。

@font-face {
  font-family: "CentralLiShu";
  src: url("/CentralLiShu.ttf");
}
.piece-text {
  font-family: CentralLiShu, fangsong;
}      

如果想了解我是如何压缩字体文件的,你可以阅读文章《基于svg和ttf(字体文件),我仅用6kb就画完了象棋所有棋子》。

问题

之前我是通过FontEditor这个在线网站编辑字体的,其实当时遇到过在MacOS上字体不居中的问题,我手动调整了每个字体的位置解决了。下图是文章内容截图:

CSS自定义字体 竖向偏移怎么办?聊聊字体文件的字体度量、上升、下降

我通过Google搜索了为什么文字不居中,结果相关的问题都非常少,怀疑是跟自定义字体有关。最终,我找到了“字体度量”这个名词。

现在我才知道了文字不居中的根本原因:字体度量。

如何解决问题

在字体编辑器上,点「设置」,可以打开「字体度量」。包括如下属性:

CSS自定义字体 竖向偏移怎么办?聊聊字体文件的字体度量、上升、下降

重点关注前3行的属性:上升、下降、win上升、win下降、typo上升、typo下降。

我发现win下降的值明显大于其他值,也许这就是导致windows下字体向下偏移的原因吧。

我发现右侧有个“计算”按钮,点击后,这些上升、下降值重新计算了:

CSS自定义字体 竖向偏移怎么办?聊聊字体文件的字体度量、上升、下降

我立马导出ttf文件,去MacOS和Windows上验证,发现字体都居中了!现在,问题解决!

但是,为什么呢?

字体度量

字体度量主要包括:

  • ascent: 顶部参考线(不推荐字体超出)。
  • capHeight: 大写字母H的高度的参考线。
  • xHeight: 小写字母x的高度的参考线。
  • Baseline: 大小不同的文字排列一行时,默认是以他们的Baseline对齐的(不能用底部参考线对齐,例如​

    ​pP​

    ​如果底部对齐,你都难以区分大小写了)。
  • descent: 底部参考线(不推荐字体超出)。

出于历史原因,至少有三组数值是用来处理字体度量的。它们名为 hhea、typo(又名 sTypo 或 OS/2)和 win(或称 usWin)量度。取决于在何种操作系统上使用的哪一款软件,在屏幕上渲染字体时,会使用不同的度量。

hhea 指 OpenType 表 hhea。Apple 设备使用这些值来渲染。typo 和 win 的值是 OpenType OS/2 表的一部分,包括​

​sTypoAscender​

​​ ​

​sTypoDescender​

​​ ​

​sTypoLineGap​

​​ ​

​usWinAscent​

​​ ​

​usWinDescent​

​。Windows会使用win值。

——引用自Glyphs字体软件的科普文章。

也就是说,我们的字体文件中,哪怕你定义了一个字体的矢量图,但是它的垂直坐标偏移还是要额外设定的。在OS/2中,我找到了详细的规范。如下图:

CSS自定义字体 竖向偏移怎么办?聊聊字体文件的字体度量、上升、下降

表格中描述是:

  • 在hhea表中,不需要定义typo值。
  • Windows 的上升指标 usWinAscent 计算为 Windows ANSI 字符集中所有字符的 yMax。
  • Windows 的下降指标 usWinDescent 计算为 Windows ANSI 字符集中所有字符的 -yMin。

写在最后