算法与数据结构 / regex · Unicode 字符模型与一个自研引擎 / 竖排朝向:同一个字,横排立着、竖排可能要躺倒 待审核 10 / 36
vo · Vertical_Orientation · UAX #50

竖排朝向:同一个字,横排立着、竖排可能要躺倒

把一段中日文从横排转成竖排(writing-mode: vertical-rl),汉字、假名原样立着,可夹在中间的拉丁字母、数字、半角括号会整体躺倒 90°。这不是浏览器随手转的:每个 code point 在 UCD 里都记了一栏 Vertical_Orientationvo),由 UAX #50 定义——横排时它毫无作用,一进竖排就逐字决定朝向。它和 General_Category / Script 一样,是码点的固有档案;区别是 JS 的 \p{…} 并不暴露它,和 Block 一样。

1 · 两个 CSS 属性

writing-mode: vertical-rl 把文本流竖排、列从右往左推进;text-orientation 再决定每个字的朝向,三个取值:mixed(默认,按各字的 vo 逐字决定)、upright(强制全部正立,连拉丁也立起来)、sideways(强制全部旋转)。

图 1-1 · 同一串文本在三种 text-orientation 下的竖排渲染,以及逐字的 vo 取值拆解。可换文本或点预设。

建议 · 三列内容完全一样,只有 text-orientation 不同。中间那列(默认 mixed)就是平时见到的竖排日文——它逐字查 vo:汉字与全角假名 vo=U 立着,拉丁与数字 vo=R 躺倒。右两列把 vo 整段覆盖掉,所以同一个拉丁字母在三列里能立、能躺、能保持。

注 · 竖排不是日文专属。自上而下、自右而左的竖排,本是整个汉字文化圈(中 / 日 / 韩 / 越)共同的传统方向——源头是竹简:窄长竹片一列一列写、卷收时自右展开。现代简体中文已转横排为主,但繁体中文(台 / 港)的书籍、报纸标题仍大量竖排,古籍影印、书法、对联、牌匾更几乎只用竖排;日文「縦書き」与之同源。vo 是 Unicode 层面的属性,对 CJK 各语言统一(同一批汉字与标点码点),所以本页所有示例对中文竖排同样成立。

2 · vo 的四个取值

上面 mixed 列逐字查的就是 vo。它有四个取值,U / R 是固定朝向,Tu / Tr 是「变换类」——先看字体里有没有竖排专用字形(OpenType vert 特性,把字符摆到竖排该在的位置与形状),有就用它,没有才回退。回退到正立的是 Tu,回退到旋转的是 Tr

表 2-1 · Vertical_Orientation 的四个取值及其典型字符。
vo 含义 竖排里怎么显示 典型字符
U Upright 原样正立,和字符表里一个朝向 漢字、ひらがな 、カタカナ 、中点
R Rotated 顺时针旋转 90°(躺倒) 拉丁 A–z、数字 0–9、半角 ( ) : ;、破折号 、省略号
Tu Transformed → Upright 有竖排字形就用,否则正立 读点句点 、小书写假名 ゃ っ、全角 ! , . ?
Tr Transformed → Rotated 有竖排字形就用,否则旋转 各种括号 「」『』〈〉【】、长音 、波浪 、全角 ():、引号 “ ” ‘ ’

警示 · 关键的不对称在于:U / R 是写死的,任何字体、任何浏览器都一样。但 Tu / Tr 把最终样子交给了字体——明朝 / 宋体类字体多半备了这些标点的竖排字形(摆到字格右上、或换成竖排专用形),黑体与系统 fallback 字体则常常没有。一旦缺字形,该回退成什么就成了下一节那桩悬案的全部争点。

3 · 悬案:竖排引号该转还是该立

引号 U+2018 / 2019 / 201C / 201DvoTr——按定义,字体缺竖排字形时应当回退旋转。现实里各浏览器并不一致。

图 3-1 · 一段含 Tr 引号、Tr 括号与 R 破折号的竖排文本,由当前浏览器与字体实际渲染。

另有一处常被忽略的分流:中文(尤其繁体竖排)与日文,正文里更常用直角引号 「」 『』U+300C 等,同样 vo=Tr)。它们是为 CJK 设计的,字体几乎都备了竖排字形,竖排里稳定呈现为左上与右下的角标,落不到「转还是立」的争议里。真正出问题的是借来的西式弯引号 “ ”U+201C 等):字体常常没给它们配竖排字形,各浏览器的回退分歧才暴露出来——这也是台 / 港竖排排版规范偏好直角引号的原因之一。

警示 · 分歧在于:同一段、同一个 vo=Tr 引号,在缺竖排字形时,Firefox 八年前就改成回退旋转(符合 Tr 定义),Safari 大体相同;而 Chrome(报告称约 148 起)默认正立显示。问题出在 CSS Writing Modes 规范的措辞:它只说浏览器 may wish to(不妨)在字形缺失时合成——太松,留了「正立也不算违规」的口子。

建议 · 村上真雄在 CSSWG issue #14078 主张把这句从 may wish to 收紧为 should / are expected to,强制:字体缺竖排字形时,vo=Tr 应回退旋转。截至本页写就,这仍是进行中的规范讨论(核对于 2026-08)——vo 在码点层定义得很清楚(Tr 等于回退旋转),可「字体缺字形时浏览器到底合成与否」这道缝没焊死,于是同一个竖排引号在三个浏览器里能呈现出三种样子。

注 · 和别的页串起来看:vo 是竖排版的「显示随上下文变」,正如 Han 统一 是「字形随 lang 变」——两者都说明 === 与正则只认码点,而屏幕上的样子还受书写模式、字体与语言摆布。竖排引号这桩悬案,和 bidi 重排 一样,都是「存储一个样、显示另一个样」。

4 · 参考文献

  1. Unicode. UAX #50: Unicode Vertical Text Layout. 竖排朝向的源头标准:vo 四个取值的定义、未分配码点的默认区间(CJK 相关默认 U、其余默认 R)、与字体竖排替代字形的关系。本页每格的 vo 值与默认规则照它的 VerticalOrientation.txt 实现。unicode.org
  2. W3C. CSS Writing Modes Level 4. writing-modetext-orientation 两个属性的规范出处,以及那句引发争议的「字体缺竖排字形时浏览器合成」措辞。w3.org
  3. W3C. public-i18n-japanese:竖排引号朝向讨论. 村上真雄报告 Chrome 把 vo=Tr 引号正立显示、与 Firefox / Safari 的旋转回退分歧,并主张收紧规范措辞。本页第 3 节即据此线索。lists.w3.org
  4. CSSWG. csswg-drafts issue #14078. 对应的规范修订提案:把字形合成那句从 may wish to 改成 should / are expected to。github.com
  5. MDN. text-orientation 与 writing-mode. 两个属性的取值、浏览器支持与示例。developer.mozilla.org