整页 RTL 必须设在 <html> 上,而非 <body> 或 <div>;仅给 <body> 或 <div> 加 dir="rtl" 无法触发浏览器整套 RTL 行为链,包括光标、Tab 顺序、Flex 主轴、滚动条等。

整页 RTL 必须设在 <html> 上,不是 <body> 或 <div>
只给 <body> 或某个 <div> 加 dir="rtl",表单光标、Tab 键顺序、Flex 主轴起点、甚至滚动条位置都不会翻转——浏览器只在 <html> 标签上看到 dir 时才激活整套 RTL 行为链。
常见踩坑点包括:
- SSR 渲染漏掉
<html lang="ar" dir="rtl">,hydration 后方向不一致 - 客户端切换语言时只改
document.body.dir,但document.documentElement.dir没同步,输入框光标仍从左入 - 第三方 UI 库(如 MUI、Ant Design)依赖
<html>的继承方向生成类名(如ms-2→me-2),根方向错,样式直接失效
dir="auto" 在生产环境几乎不可靠
dir="auto" 看似省事,但触发条件极苛刻,真实内容常让它误判:
- 首字符是数字(
"123 أهلا")、ASCII 字母("Hello عالم")、空格或中文 → 全部 fallback 到ltr - 动态插入内容(如
el.innerHTML = apiText)后不会重新触发方向检测 - Safari 对带变音符号的阿拉伯字符支持不稳定,Chrome/Firefox 行为也不完全一致
线上项目应明确指定 dir="ltr" 或 dir="rtl";仅在低风险用户评论预览等场景谨慎使用 dir="auto",且需前端校验首非标点字符。
立即学习“前端免费学习笔记(深入)”;
混合文本必须用 <bdi> 隔离,不是靠 dir 覆盖
当一段内容来自 API(如用户名、搜索词),方向不确定且可能混排("أحمد123"),直接写 {{username}} 会污染父级 Bidi 上下文,导致整段文字顺序错乱。
正确做法是:
- 用
<bdi>包裹:<bdi>{{username}}</bdi>,它自动创建独立双向隔离上下文 - 避免用
<bdo dir="rtl">—— 它强制重排,会把"123"显示成"321",仅用于调试 - 不要只写
style="direction: rtl",它不触发 Bidi 算法,复制到记事本仍乱序
<input> 和 <textarea> 必须显式设 dir,CSS direction 无效
<input> 和 <textarea> 的光标起始位置、退格行为、选区方向、placeholder 渲染逻辑,都由 dir 属性决定,direction: rtl 完全不起作用。
实操要点:
- RTL 页面中,每个
<input type="text">和<textarea>都要加dir="rtl" - 含英文 URL 或人名的阿拉伯语段落,应在内联元素上单独设
dir="ltr"(如<a href="#" dir="ltr">https://example.com</a>) -
<select>下拉项、<button>文本方向也受dir影响,不能仅靠 CSS 对齐
真正难的不是加 dir,而是判断哪一层该继承、哪一层该隔离、哪一层该用 CSS 替代——多数 bug 都出在“以为加了 dir 就万事大吉”。



















