必须在<html>上设dir="rtl"并同步设置lang,否则光标、焦点、Flex等RTL行为全错;仅局部设dir或混用direction/style会导致渲染异常、可访问性降级及双向文本混乱。

必须在 <html> 上设 dir="rtl",否则光标、焦点、Flex 行为全错
浏览器只在根元素带 dir 属性时,才完整启用 RTL 感知机制。仅给 <body> 或某个 <div> 加 dir="rtl",会导致:
-
<input>和<textarea>光标从左入、退格方向反、双击选词错乱 - Tab 焦点流不翻转(仍按 LTR 顺序跳转)
-
<select>下拉项未镜像,滚动条卡在右侧而非左侧 - Flex 主轴起点不变,
justify-content: flex-start还是往左对齐
正确写法是:<html dir="rtl" lang="ar">。注意 lang 必须同步设置,否则字体连字、数字样式、屏幕阅读器语音规则均不生效。
动态切换方向时,只改 document.documentElement.dir,别碰局部节点
客户端语言切换不能只改 body 或某个容器的 dir,否则会破坏继承链和第三方库逻辑(如 MUI 的 me-2 → ms-2 映射)。必须成对操作:
- 用
document.documentElement.setAttribute("dir", "rtl")或直接赋值document.documentElement.dir = "rtl" - 避免混合使用:不要一边改
body.dir,一边又设html.lang,hydration 不一致会触发 SSR/CSR 渲染差异 - 服务端渲染(SSR)必须初始输出带
dir的<html>,否则首屏闪动 + 可访问性降级
混合文本别信 dir="auto",该用 <bdi> 就用
dir="auto" 在真实场景中几乎不可靠:
立即学习“前端免费学习笔记(深入)”;
- 首字符是空格、数字、中文、括号或变音符号时,Chrome/Safari 判断不一致
- JS 动态插入内容后不会重新检测(比如 API 返回的用户名
"أحمد123") - 中文开头默认 LTR,阿拉伯字母混在中文后也不会触发重排
替代方案是显式隔离:
- 嵌入英文 URL、版本号等 LTR 内容时,用
<bdi dir="ltr">https://example.com</bdi> - 避免用
<bdo>—— 它强制字符级翻转,破坏语义和复制粘贴顺序 - 不要用
style="direction: ltr"替代<bdi>,它不参与 Unicode 双向算法(UBA),复制到记事本仍是乱序
dir 和 direction 不可互换,但得一起用
dir 是 HTML 语义属性,决定光标、Tab 流、剪贴板粘贴顺序、Flex 轴向起点;direction: rtl 只影响盒内文本流和部分布局,无法改变表单焦点逻辑。
-
text-align: right是视觉右对齐,不是逻辑终点对齐;应统一用text-align: end - 物理属性如
margin-left、float: left、left: 10px不随dir自动翻转,需改用margin-inline-start、float: inline-start、inset-inline-start: 10px -
flex-direction: row-reverse是常见误操作:若容器已设dir="rtl",再加它会导致子项顺序被翻转两次
真正难的不是加 dir,而是判断哪一层该继承、哪一层该隔离、哪一层该用 <bdi>——多数方向 bug 都出在“以为设了 dir="rtl" 就结束了”,结果输入框光标还在左边,或者阿拉伯语里的英文 URL 被拆成两行还反向换行。



















