移动端 Safari 对 ruby 的 display 计算有偏差,需显式声明 ruby { display: ruby; },并配合固定字号、line-height: 1、bdi 包裹、禁用 text-rendering 等措施确保注音始终粘附基字。

移动端 Safari 对 ruby 的 display 计算有偏差
iOS Safari(尤其是 16.4 之前版本)会把 ruby 当作普通 inline 元素处理,不触发原生注音布局逻辑,导致 rt 堆叠在基字右侧、字体未缩放、甚至垂直偏移严重。这不是 bug,而是 WebKit 对 HTML5 规范的渐进式实现差异。
必须显式声明:ruby { display: ruby; }——这个声明在 Chrome/Firefox 中也有效,且不会破坏语义,是目前最稳的兜底写法。
不要依赖 vertical-align: super 或 position: relative 手动调位置,它会让 rt 相对于整行偏移,而非相对于基字;屏幕阅读器也会失去对齐关系。
Android WebView 中 rt 渲染不稳定,尤其在混合排版时
部分安卓系统(如旧版 Samsung Internet、基于 Chromium 80–90 的 WebView)会忽略 rt 的上标行为,或强制继承父级 font-size,造成拼音和汉字一样大、挤占行高。
立即学习“前端免费学习笔记(深入)”;
解决要点:
-
rt必须设固定像素字号(如font-size: 12px),避免用em或百分比——不同 WebView 对基准字号推导不一致 - 加
line-height: 1防止默认行高撑开ruby容器高度 - 若页面含 RTL 文本(如阿拉伯语混排中文),
ruby外层必须套<bdi>,否则拼音会被拉向右端 - 禁用
text-rendering: optimizeLegibility,某些安卓 WebView 在开启该属性时会跳过rt的渲染路径
viewport 和字体缩放会放大 ruby 的错位风险
移动端用户常双指缩放,而 ruby 的默认渲染逻辑不响应动态缩放:基字随页面放大,rt 却可能卡在原始尺寸,视觉上“飘”在空中。
应对方式:
- 在
<head>中确保有标准 viewport:<meta name="viewport" content="width=device-width, initial-scale=1.0"> - 避免设置
user-scalable=no—— 屏幕阅读器依赖缩放功能,禁用后会损害可访问性 - 不给
ruby设transform: scale(),这会破坏内联流,导致换行断裂 - 测试时务必开启 iOS 的「显示字幕」和「增大字体」辅助功能,部分 Safari 版本在启用后会完全跳过
rt渲染
rp 标签在移动端几乎无实际价值,建议服务端过滤
rp 的设计目标是给 IE ≤10 显示括号 fallback,但现代移动端浏览器(包括 iOS Safari、Chrome for Android、Firefox for Android)既不隐藏它,也不按规范渲染括号——结果是 Chrome 显示“(hàn)”,Safari 却只显示 “hàn”,同一段 HTML 出现两种视觉。
更糟的是,某些安卓 WebView 会把 rp 当作普通文本渲染,导致括号和拼音并列,比如 “(hàn)hàn”。
稳妥做法:
- 服务端根据 UA 判断是否为移动设备 + Blink/WebKit 内核,直接不输出
rp - 若必须前端处理,用 JS 移除(注意时机:DOMContentLoaded 后,不能等 window.load):
document.querySelectorAll('ruby rt rp').forEach(el => el.remove()) - 绝对不要用 CSS
display: none隐藏rp—— 部分旧 WebView 仍会将其内容计入可访问性树,读屏软件可能念出括号
真正难的不是让拼音显示出来,而是让它始终“粘”在对应的那个字上——哪怕用户缩放、横屏、切换字体、打开辅助功能。移动端的 ruby 不是写一次就能跑通的静态结构,它需要在 display、font-size、bidi、viewport 四个层面同时受控,漏掉任何一环,视觉或语义就断了。



















