#78 font-size-adjust 简谈
网页字体微调
旧闻一则:Safari 17.0 支持 font-size-adjust
更多特性,可以直接使用 from-font
值和双值语法,包括 CJK 文字 ic-height
值。这个 CSS 特性解决的是网页字体 fallback 场景下不同字体的大小对齐问题,尽量让保持字体大小一致,增加可读性。
举个例子
为了效果直接,我挑了个极端的对比。上图中衬线字体为 Google Sans,中间特殊字体为 Baskerville,默认都是 16px 字号,「调整前」Baskerville 视觉上明显小了一些。font-size-adjust
可以单独微调字号,让其按照 x-height 或其他标准对齐。
font-size: 16px;
font-size-adjust: 0.5;
X-height 对一款西文字体的风格体现很重要,高于均值的 x-height 字体在小字号中更易读,低于均值的 x-height 字体更不落窠臼,而 x-height 过高和过低都会导致难以辨认字形。
在正文排版中,基线对齐是标准,按照相近的 x-height 高度排版便能起到对齐效果。font-size-adjust
默认值便是如此,双值语法即:
font-size-adjust: ex-height 0.5;
0.5 代表待调整字体的 x-height 高度之于 font-family
首选字体的 font-size
比例,在这里也就是,我们想让 Baskerville 的x-height 和 Google Sans 一样,即 16 * 0.5 = 8px 高。
至于0.5 怎么得出来的了——WWDC 23 的 What’s new in CSS 视频中会说,大部分比值都在 0.5 左右徘徊:
x-height / font size ≈ 0.5
所以只要试出一个自己满意的值即可。当然如果想精准一些,也可以自己到软件里手动测量。
如图,为了取整(和在 Figma 里演示)方便,均为 80px 字号的字体,实际量得Google Sans 的 x-height 为41(取整),Baskerville 的 x-height 为 32(取整)。一个比例 0.5 一个比例 0.4,相差甚远。
对 Baskerville 进行 font-size-adjust
时即可设置为 0.5,反之如果对 Google Sans 调整,即可设置为 0.4。
当然上述只是模糊的参考数值。如果懒得计算也没关系,可以直接试试:
font-size-adjust: from-font;
这样会自动调用字体度量(metrics)来计算,比如 Google Sans 的 x-height 度量为 510,em 为 1000,实际比例就是 0.51。像 Baskerville 这样的老 TTF 字体,em 为 2048,x-height 为 819,实际比例就是 0.3999。
其他特性介绍
除了 ex-height
,font-size-adjust
还支持 cap-height
, ch-width
, ic-width
, ic-height
属性,如图。
图很清晰:
cap-height
指的是大写高度,使用 H 和 I 等字母比较方便测量,Figma 中给字体开启 vertical trim 也是该高度;ch-width
指的是字体中数字 0 (唯一指定 U+0030)的步进宽度;ic-width
ic-height
指的是 CJK 文字中「水」(唯一指定 U+6C34,不是康熙部首 U+2F54)的步进宽度和高度;
所以这么一看,上面 WWDC 23 那张图多少有些不太严谨🤭。
中英混排
从实际出发,这次以 Noto Sans SC 和 Google Sans 混排为例,两者组合是 Google 大中华区不得不品尝的设计风味之一。
与西文字体不同的是,中文不能复用其度量标准。虽然都是在观察负空间和阅读轮廓线,但中文更看重字面、重心和中宫,中宫常与西文的 x-height 相比较,但只处于感知层面没有数值描述。不同结构的文字和其他语言组合也需要考究一番。
Noto Sans SC 中既有英文也有中文,网页实际渲染时会按照英文部分渲染基线和其他度量。所以单就 ic-height
来说并非特殊属性。比如下面一个常见的例子:使用数字和中文搭配成 label 文字的组合。
未调整情况下,我们会发现「条回复」明显大于数字,特别是顶部高出一头的感觉很明显。分别使用三种特性对中文进行调整,可以看到中文和数字对齐了一些,同时三种调整几乎没有区别。(注意:这里的汉字首选字体均单独设置为 Noto Sans SC)
如上图各度量使用 Figma 基础设置便可大致显现。
- 首先 Figma 中字体会自带基线显示;
- 将文本 line height 设置为 auto 即可显示行高轮廓;
- 将文本 type settings 里切换 vertical trim 即可显示 cap height,或者打出大写字母 M;
- 打出小写 x,其高度即为 x-height;
- 这里的 ic-height 可按照升部+降部计算;
从设计角度看,我们可以先逆过来调整不同文本到一定和谐的比例,然后再去统计此时各个度量数值,从而计算出比例。
但是到环境更复杂的正文中,有时调整局部反而破坏了整体连续性。
由于中文与英文衔接处不固定,所以难以大幅度改动排版。比如此例中的「使用 AC」处,一直最稳定的默认调整 from-font
翻车,AC 顶部明显比「用」字高出一头,显得整体中文反而较小。
原因大概在于,设置 ic-height
的前提是基线位置不变,汉字的顶部趋近于英文顶部时,下方并不会相应对齐,从而比例不太和谐。所以此时,在默认比例基础上稍微增加一些数值会更好一些。
其他拓展实例
中文不同字体混排
像我们这种市井设计师,可能会碰到一些比较逆天的排版。这时候中文内不同字体也可以使用 font-size-adjust
调整排版。
上图中,「宇宙洪荒」使用了站酷快乐体,其他文字使用了 Noto Sans SC。可以看到快乐体整体偏小(当然字重也不匹配,这里先忽略)。到 Figma 里看了一下,同样都是 100 号字体时,快乐体字宽 92,字高 100。所以设置 ic-width
为 100 / 92 ≈ 1.087,效果如图所示。
阿拉伯字体实验
某个平行世界的我可能在研究 8 世纪的炼金文籍,但这个世界的我对阿拉伯文一无所知。在 W3C 的文档看到多层基线时我就先撤退了。直接看看效果:
上图阿拉伯文是我随便在 Google Font 上找到的字体 Ruwudu,直接用 from-font 调整后高度有所改善。但 Ruwudu 并非是正宗使用 alef height、joining line 或 Meem Depth 等度量的阿拉伯文字体,本质上依靠的还是字体内西文字体的度量,所以实际效果待定。
兼容
目前 font-size-adjust 仅 Firefox (3-120)和 Safari (16.4-17.0)支持,Chrome 可在 flags 里开启。而双值语法特性 (Two-value syntax)仅 Firefox (92-120)和 Safari (17.0)支持,Chrome 不可兼容。
上文图例均在 Safari 17.0 实现。
参考
本次成文离不开各方资料参考:
- MDN 文档
- WebKit Features in Safari 17.0
- CSS Fonts Module Level 5
- Glyph Metrics - Freetype
- What’s new in CSS - WWDC23
一些常见字体比例小工具:
延伸阅读
如感兴趣读者可以继续延伸阅读:
- font-size-adjust 可追溯到 2008 年
- 网易云团队探索过文字垂直居中的其他方式实现
- Skia 引擎下中文字号微调解析(CSDN 警告)
- 汉字设计中的度量标准 其一 其二 其三
- Bilingual Lettering — (4) Consistency
- Exploring x-height & the em square - Google Font Knowledge
- RTL Styling 101
如果你觉得文章对你有些帮助,可以请我的猫吃罐头 ↓