从右到左装饰字符的陷阱
摘要
摩尼教花饰Unicode字符具有从右到左的方向类型,可能导致网页布局中出现意外的文本重排。本文解释了该问题,并提供了使用HTML的<bdi>标签或CSS的unicode-bidi属性进行修复的方法。
暂无内容
查看缓存全文
缓存时间: 2026/07/11 07:23
# 从右到左装饰字符的陷阱 - Vox Silva
来源:https://blog.alexbeals.com/posts/the-footgun-of-right-to-left-decorative-characters
2026年5月19日
花饰(Fleurons)和其他印刷装饰元素是排版中使用的装饰性符号。其中许多已经进入数字时代的字体中,Unicode 支持经典花饰如 ❦ 和 ❧¹,以及从恰如其名的 ❀(白花饰)到鲜为人知的 ᪥(Tai Tham 符号 Dokmai²)等附加符号——这些符号已转变为视觉指示符。我最近尝试用 𐫱 作为日期和文章分类之间的分隔符,但发现它意外地渲染在标签中间:
它*应该*像这样渲染。为什么不会呢?
## 摩尼教与 Unicode
𐫱 是摩尼教标点花饰(Manichaean Punctuation Fleuron),属于 Unicode 中用于改编摩尼教宗教文本的一个区块。如果你想知道摩尼教是什么,它是公元3世纪的一个世界性宗教,由于积极迫害、与基督教、伊斯兰教和佛教的竞争,以及与之捆绑的帝国灭亡而崩溃³。如果你不关心,只需知道他们有一个漂亮的花形符号……并且是从右到左书写的。
虽然大多数摩尼教文字都是纯从右到左书写,但在网站上它们并不那么受限⁴。Chrome 使用的任何渲染算法在布局文本时都需要处理包含从左到右和从右到左字符的双向文本。Unicode 有详尽的描述,因此有一个 Unicode 双向算法(Unicode Bidirectional Algorithm)来解释如何做到这一点,但由于 Unicode 如此复杂,这需要约 20,000 字和 51 次修订⁵——我们只看个摘要。每个字符都有一个双向字符类型(可在 UnicodeData.txt 中查看)。这可以是强类型,如 `L`(左)用于字母 "A" 或 `R`(右)用于希伯来文本;弱类型,如 `EN` 用于欧洲数字(如 0);或中性类型,如 `WS` 用于空白(如制表符和空格)。强类型会优先,弱类型会遵循其周围的强类型。
摩尼教花饰是 `R` 类型,因此它会重新排列数字 `400` 这个弱区块(尽管它们内部仍保持为 400 而非 004),从而将 `𐫱 400 Divisadero` 渲染为 "𐫱400 Divisadero"。
## 使用 HTML 和 CSS 修复
幸好这是可以修复的——只要我们记得去做!我们可以用 `<bdi>` HTML 标签包裹花饰,以将其方向性与周围文本隔离:
`<bdi>𐫱</bdi> 400 Divisadero` 现在会渲染为:
𐫱 400 Divisadero。
你也可以用 CSS 样式 `unicode-bidi: bidi-override;` 达到同样效果⁶:
`<span style="unicode-bidi: bidi-override;">𐫱</span> 400 Divisadero`,它在浏览器中支持度*略好*⁷。
*下次你用到像 𞢹 或 𐩕 这样的符号时,记得这样做。*
---
¹ 这些正在慢慢引入博客样式中,正式文章 Coming Soon™。
² Dokmai 在北泰语或老挝语等 Tai Tham 文字中意为“花”。
³ 而且他们愚蠢地不允许死后皈依者,不像某些*快速增长的宗教*。
⁴ 看看我,妈妈!עברית(HEBREW)和 عربي(ARABIC)和 𐫖𐫀𐫗𐫏𐫐𐫏𐫀𐫗(MANICHAEAN)都在一个句子里!
⁵ 如果你好奇,这里是表格。
⁶ “Bidi” 代表双向(bi-directional)。
⁷ 不过谁真的在乎 IE 呢。
相似文章
解读太斯米
本文探讨了阿拉伯文字编排在历史和技术上的挑战,重点论述了连字对太斯米短语的重要性,以及Unicode在解决这一问题中的作用。
交互式介绍:渲染阿拉伯字体排版的精彩体验及其技术债
一位前端工程师深入探讨在网络上渲染阿拉伯文字的历史与技术挑战,涵盖CSS限制、字体造型以及数个世纪的排版演变。
Hershey是一种文本化的矢量字体格式
本文介绍了Hershey矢量字体格式,这是一种使用坐标编码系统的字形文本表示法,其中字母映射到有符号值,并包含示例和相关资源链接。
Unicode 字符串的等价性很奇怪 (2016)
Unicode 字符串等价性很复杂,尤其是涉及校对规则时,会导致意外的结果,例如删除控制字符和非确定性分组。作者讨论了在数据库系统中正确实现 Unicode 支持所面临的挑战。
升级资源字符串到Unicode时,别忘了指定L前缀
解释:当在Windows资源字符串中使用Unicode转义序列(如\x2019)时,必须在字符串前加上L前缀使其成为宽字符字符串;否则转义序列会被误解为8位序列。