真正起效必须从<html>开始设dir="rtl",因为只有它能触发Unicode双向算法全局生效;仅在<p>或<div>上设置会导致光标、表单、Flex布局、数字顺序等行为异常。

只给 <p> 或 <div> 加 dir="rtl",阿拉伯语文字确实会靠右,但光标、数字顺序、表单行为全乱——真正起效必须从 <html> 开始设。
为什么不能只在段落上加 dir="rtl"
浏览器对 RTL 的支持不是“文字对齐”这么简单。它依赖 Unicode 双向算法(UBA)启动完整上下文:<html dir="rtl"> 是唯一能触发 UBA 全局生效的锚点。只在 <p dir="rtl"> 上设,会导致:
-
<input>和<textarea>光标仍停在左侧,输入阿拉伯语时首字跳到右边 - Tab 键焦点还是左→右移动,违反 RTL 用户直觉
- Flex 容器中按钮顺序不翻转,
justify-content: flex-start依然对齐左边缘 - 旧版 Safari 甚至忽略继承,
<span>里的阿拉伯数字“١٢٣”被错误重排为“٣٢١”
<html> 上设 dir="rtl" 后,还要同步 lang
lang 不是可选装饰,它直接影响字体连字、数字样式、屏幕阅读器语音规则。阿拉伯语必须配 lang="ar",希伯来语用 lang="he",波斯语用 lang="fa":
<html dir="rtl" lang="ar">
动态切换时,JS 必须成对修改:
立即学习“前端免费学习笔记(深入)”;
document.documentElement.setAttribute("dir", "rtl");<br>document.documentElement.setAttribute("lang", "ar");
漏掉 lang,Chrome 里阿拉伯数字可能显示为 ASCII 形式(0-9),而不是本地数字(٠-٩)。
阿拉伯语里混英文或数字,顺序还是乱?用 <bdi>
即使整页 dir="rtl",像 "تحديث إلى v2.4.1" 这种混合内容仍会显示成 "1.4.2 v تحديث إلى" —— 因为 UBA 没被隔离触发。解决方法不是写 CSS,而是语义化包裹:
<button dir="rtl">تحديث إلى <bdi>v2.4.1</bdi></button>
<bdi> 创建独立双向隔离上下文,不干扰父级方向,也不强制反转数字顺序(对比 <bdo dir="rtl"> 会把 "123" 显示为 "321")。对 API 返回的用户名、评论等动态内容,统一用 <bdi>{{text}}</bdi>,别信 dir="auto" —— 它在 Safari 旧版和 Android WebView 中常失效。
<input> 和 <textarea> 必须单独加 dir
它们不会完全继承 <html> 的方向。不显式声明,光标初始位置、退格逻辑、粘贴顺序都按 LTR 处理:
<input type="text" dir="rtl"><br><textarea dir="rtl"></textarea>
如果同一个页面要支持双语输入(比如阿拉伯语用户填英文邮箱),可用 dir="auto",但仅限于表单控件本身;千万别给 <body> 或容器设 dir="auto" —— 首字符是 ASCII 就永远判为 LTR,后面全是阿拉伯语也无效。
最易被忽略的点:所有含 left/right 的 CSS 属性(margin-left、float: right、left: 4px)都不会随 dir="rtl" 自动翻转,必须改用逻辑属性(margin-inline-start、float: inline-start、inset-inline-start)或降级写法(dir(rtl) { right: 4px; })。



















