国学经典必须每个字单独套ruby,因虚词、多音字、通假字极多且一字一义一读,浏览器无法自动分词;rb缺失会导致Safari等降级渲染、屏幕阅读器朗读异常,故须严格逐字用ruby+rb+rt+rp包裹。

直接用 ruby + rb + rt + rp 逐字包裹,不合并、不跳过、不省略 rb,否则 Safari 和部分安卓 WebView 会错位或静默失效。
为什么国学经典必须每个字单独套 ruby
古籍如《论语》《道德经》里,“之乎者也”“道可道”等虚词、多音字、通假字极多,且一字一义、一字一读。浏览器无法自动分词或判断语境——ruby 的语义锚点只认「一个 rb 对应一个 rt」。若写成 <ruby>不可道<rt>bù kě dào</rt></ruby>,结果是:Safari 可能只给“道”标音,Firefox 把拼音压在“不”字右侧,屏幕阅读器朗读时跳过前两字。
- 正确做法是:
<ruby><rb>不</rb><rt>bù</rt><rp>(</rp><rp>)</rp></ruby><ruby><rb>可</rb><rt>kě</rt><rp>(</rp><rp>)</rp></ruby><ruby><rb>道</rb><rt>dào</rt><rp>(</rp><rp>)</rp></ruby> - 通假字如“蚤”通“早”,需按本字注音:
<ruby><rb>蚤</rb><rt>zǎo</rt></ruby>,不能写“zǎo(通‘早’)”混在rt里 - 句读符号(、。?)不参与注音,也不应被
ruby包裹;若需强调,用span或 CSS 伪元素
rb 不是可选的,现代浏览器已不兼容无 rb 写法
很多教程仍沿用 <ruby>道<rt>dào</rt></ruby> 这种“简洁写法”,但它在 Safari 17.4+、Chrome 115+ 和多数安卓 WebView 中已触发降级:拼音不再上标,而是平铺在字后,甚至被截断。根本原因是缺失 rb 后,基字语义丢失,rt 失去定位锚点。
-
rb必须显式包裹每一个被注音汉字,哪怕只是单字 -
rb内不能含空格、换行或内联标签(如em、strong),否则结构断裂 - 若原文含 HTML 实体(如
或),需先转义或过滤,否则 DOM 解析失败
动态注入时最容易漏掉的三处校验
国学网页常从 JSON 加载古文+拼音对,用 JS 拼接 HTML。此时结构完整性极易被破坏,不是样式问题,而是语义失效。
立即学习“前端免费学习笔记(深入)”;
- 检查拼音字符串是否含全角字符或中文标点(如“dào”“dào。”),这些会导致 Safari 渲染异常或字体 fallback 失败
- 确保每个
rb和rt数量严格相等,且顺序一致;常见错误是拼音数组比汉字少一位(如漏掉句末“也”字),导致最后一个rt被忽略 - 禁用
innerHTML = str直接赋值;改用element.append(...fragments)或 DOMPurify.sanitize(str, { ALLOWED_TAGS: ['ruby', 'rb', 'rt', 'rp'] }) 过滤 XSS 风险
CSS 微调只动三处,别碰定位逻辑
国学页面常需适配小屏、高缩放比和印刷导出,但 ruby 的排版引擎极其敏感。强行用 position: absolute 或 transform 移动 rt,会导致打印时错位、TTS 朗读偏移、iOS 缩放后重叠。
- 只设
ruby rt { font-size: 0.65em; line-height: 1; }—— 这是触发浏览器内置 ruby 对齐逻辑的最小必要条件 - 父容器加
line-height: 1.9;,防止多行注音挤压基字行高 - 全局加
ruby { ruby-position: over; },避免竖排模式下注音跑到左侧(古籍竖排仍常见)
最麻烦的不是写错结构,而是写对了却没验证——尤其在 iOS Safari 和微信内置 WebView 里,rp 可能不显示括号,rb 缺失时又不报错,只静默降级。上线前务必用真机打开开发者工具,检查 DOM 是否完整、computed style 中 rt 是否有 display: ruby-text。



















