:dir(rtl)仅匹配显式dir="rtl"或强rtl字符推断的元素,不响应direction: rtl或lang属性;需在设dir="rtl"并配合逻辑属性(如margin-inline-start)或手动翻转(如transform: scalex(-1)),避免混用[dir="rtl"]及滥用物理属性。

:dir(rtl) 不是自动翻转开关,它只提供方向条件,镜像逻辑必须你手动写。直接加 :dir(rtl) { margin-right: 16px; } 不会“自动翻转”,反而可能在 RTL 下把间距加错边。
为什么写了 :dir(rtl) 但样式不生效
浏览器不会“猜”方向。它只匹配计算后 dir 为 rtl 的元素,而计算依据只有两个:HTML 中显式写的 dir="rtl"(如 ),或浏览器根据强 RTL 字符(如阿拉伯字母、希伯来字母)自动推断(Chrome/Firefox 支持,Safari ≤15.3 不可靠)。lang="ar" 或 lang="he" 完全不影响匹配。
SSR 页面若服务端没注入 dir 属性(比如模板默认输出 而非 ),那客户端 JS 后续加 dir 也晚了——CSS 已解析完毕,:dir(rtl) 规则压根没进匹配队列。
局部设 或 <div dir="rtl"> 不够:旧版 Safari 和部分表单控件(如 <code><input> 光标、选区)要求必须从 开始设 dir="rtl" 才能触发完整 RTL 感知机制。
:dir(rtl) 配合什么 CSS 属性最有效
优先用逻辑属性,物理属性仅作兜底。
- 间距/边距类:用
margin-inline-start/margin-inline-end替代margin-left/margin-right,它们天然响应方向,无需:dir() - 图标翻转:
transform: scaleX(-1)没有逻辑等价物,必须靠:dir(rtl)控制:.icon:dir(rtl) { transform: scaleX(-1); } - 浮动/定位:优先用
float: inline-start比float: left更安全;但若必须用物理值,就写两套:.sidebar:dir(ltr) { left: 0; }和.sidebar:dir(rtl) { right: 0; } - 慎用
text-align:它本身已响应direction,单独写text-align: right在:dir(rtl)里是冗余的;真要覆盖,优先改direction或用text-align: start
容易踩坑的混用场景
多个方向控制机制叠在一起,优先级和继承关系极易失控。
避免同时存在 [dir="rtl"] .btn 和 .btn:dir(rtl):前者只认硬编码属性,后者认计算方向,两者来源不同、匹配范围不同,CSS 优先级又一样,调试时根本分不清谁覆盖了谁。
别在全局 下直接套用第三方组件库(如 Bootstrap、Ant Design):它们默认按 LTR 设计,几乎不会监听 :dir() 或用逻辑属性,强行加 dir 会导致输入框清除按钮错位、下拉方向不翻转、光标行为异常等问题。
:dir(rtl) 不响应纯 CSS 的 direction: rtl 声明——必须由 HTML dir 属性或浏览器推断(基于字符)触发,这是最容易被忽略的底层前提。











