必须在元素上显式设置dir="rtl",否则光标、tab焦点、flex主轴、滚动条位置等关键行为全都会错乱;局部设dir仅影响uba文本重排,不改变表单控件行为与布局逻辑,且dir="auto"不可靠,混合文本须用隔离。

必须在 元素上显式设置 dir="rtl",否则光标、Tab 焦点、Flex 主轴、滚动条位置等关键行为全都会错乱。
为什么只给 <div> 或 <code> 加 dir="rtl" 不行
局部设置 dir="rtl" 仅影响该元素内 Unicode 双向算法(UBA)的文本重排上下文,但不会改变:
-
<input>和<textarea></textarea>的光标起始位置——仍从左开始,首次输入后才“跳”到右 - Tab 键在表单控件间的移动顺序——依然按 LTR 逻辑从左到右跳转
-
flex-direction: row的主轴起点——默认仍是flex-start在左侧,不会自动变为右侧 - 滚动条位置——只有
才能触发 Chrome/Firefox 将其移到左侧(取决于系统支持)
dir="auto" 在生产环境几乎不可靠
它依赖首个「强方向字符」判断方向,而这个“首字符”在真实数据中极难保证:
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
- 用户昵称是
"Ahmad"或"123 أحمد"→ 首字符为 ASCII 字母或数字,强制 fallback 到ltr - 昵称是中文
"张伟"→ 属于无方向性字符,同样 fallback 到ltr - Vue/React 中异步渲染内容(如
v-html),DOM 先渲染空字符串,dir="auto"一旦锁定就不再重算 - Safari 对带变音符号的阿拉伯字符识别不稳定,尤其旧版 WebView
结论:dir="auto" 仅适用于评论区、搜索关键词等低风险、纯展示型内联文本;所有导航、表单 label、按钮文案必须显式写死 dir="ltr" 或 dir="rtl"。
动态插入的混合文本必须用 <bdi></bdi> 隔离
API 返回的用户名、搜索词、标题等内容方向不确定,直接插入 RTL 容器会导致括号反向、数字顺序错乱、标点包裹异常:
- 错误写法:
<div dir="rtl">{{username}}</div>—— 若username是"John",整个容器 Bidi 上下文可能被带偏 - 正确写法:
<div dir="rtl"><bdi>{{username}}</bdi></div>——<bdi></bdi>自动创建独立双向隔离上下文,不污染父级 - 别用
<bdo dir="rtl"></bdo>:它会强制翻转所有字符顺序("123"显示为"321"),仅适合调试
真正难的不是加 dir,而是判断哪一层该继承、哪一层该隔离、哪一层该用 <bdi></bdi>——多数 RTL bug 都出在“以为加了 dir 就完事了”,结果混合文本卡在中间不动,或者滚动条出现在左边却没配好 overflow-x。










