ruby-align在自定义字体下失效的根源是字体加载前fallback渲染导致度量错乱,需通过document.fonts.load()监听就绪、opacity控制显示,并手动设置vertical-align和line-height确保基线对齐。

ruby-align 在自定义字体下失效的根源
不是 ruby-align: center 写错了,而是它根本没被触发——自定义字体(如 Noto Sans CJK、Source Han Serif)加载完成前,浏览器用 fallback 字体渲染 rb 和 rt,此时基字宽度、行高、基线位置全错,ruby-align 失去计算依据。等字体加载完,注音不会自动重排,导致拼音长期偏左/偏右/上下错位。
font-face 加载完成前必须禁用 ruby 渲染
直接让 ruby 元素在字体就绪前不可见,避免错位残留。关键不是等 load 事件,而是监听 document.fonts.load() 的 Promise:
document.fonts.load('1em "Noto Sans CJK SC"').then(() => {
document.documentElement.classList.add('fonts-loaded');
});
然后 CSS 中写:
.fonts-loaded ruby { opacity: 1; transition: opacity 0.2s; }
ruby { opacity: 0; }
- 不要用
display: none→ 会破坏流式布局,影响后续行高计算 - 别只监听单个字体,应覆盖所有用于
rb/rt的字体族(包括 fallback) - 若用 Web Font Loader 库,需确保其
active回调真正代表渲染就绪,而非仅下载完成
自定义字体必须显式声明 vertical-align 和 line-height
多数中文字体(尤其思源、霞鹜)默认 vertical-align: baseline,但基线位置与拼音注音所需的“字心线”不一致,ruby-align 无法补偿。必须手动对齐:
立即学习“前端免费学习笔记(深入)”;
-
rb设vertical-align: text-bottom或text-top(实测text-bottom更稳) -
rt必须设line-height: 1+font-size: 0.6em,且不能用百分比(50%在不同字体下缩放比例不一致) - 整个
ruby容器加line-height: 1.25,防止父段落继承过大的line-height挤压拼音空间 - 若字体含 OpenType 特性(如
vert),需在@font-face中启用:font-feature-settings: "vert";
Chrome 与 Safari 对 font-display: swap 的处理差异
font-display: swap 让文本立即显示,但 Chrome 会用 fallback 字体撑开 rb 宽度,Safari 则倾向收缩——同一段 HTML 在两者中拼音水平偏移量可能差 2–3px。解决方法只有两个:
- 改用
font-display: optional(需服务端支持 HTTP/2 Push 或预加载) - 放弃
swap,改用block+ 上述opacity控制,牺牲首屏可见性保对齐精度 - 若必须用
swap,得在 JS 中测量 fallback 与目标字体的getBoundingClientRect().width差值,动态为每个rb补margin-left—— 但仅适用于静态内容,动态更新会失准
最常被忽略的是:自定义字体下的 ruby 对齐不是样式问题,而是字体度量(font metrics)与浏览器排版引擎之间的一次同步失败。你调的不是 CSS,是字体加载时序和基线坐标系的映射关系。



















