Arbitrary Variants 是将合法 CSS 选择器片段用方括号注入类名前缀的机制,仅支持原生可解析的选择器(如 :nth-child、:has、::before),不支持 :focus-visible 等非 DOM 表达伪类,且不可用于 @apply。

Arbitrary Variants 的语法本质是 CSS 选择器字符串注入
它不是 Tailwind 内置的伪类变体(比如 hover: 或 first:),而是把任意合法 CSS 选择器片段,用方括号包裹后直接塞进类名前缀位置。例如 [&:nth-child(3)]:underline 最终会生成一条类似 .your-class:nth-child(3) { text-decoration: underline; } 的规则。这要求你写的括号内内容必须是浏览器能解析的原生选择器语法,且不能含 JS 表达式、变量或空格(空格需用 _ 替换)。
哪些伪类/选择器能用,哪些会失效
支持的包括::nth-child(n)、:not()、:has()(v3.4+)、::before、::after、:is()、:where() 等现代 CSS 支持的选择器;不支持的是依赖运行时状态但无对应 DOM 表达的伪类,比如 :focus-visible 无法写成 [&:focus-visible](Tailwind 不识别,也不生成对应规则)。另外,:hover 这类已有原生变体的,没必要用 arbitrary——直接写 hover:underline 更可靠、更轻量。
-
[&:nth-child(2n+1)]:bg-gray-50→ 有效,奇数子元素高亮 -
[&::before]:content-['→']→ 有效,注意单引号需保留 -
[&:not([data-disabled])]:cursor-pointer→ 有效,排除 data-disabled 元素 -
[&:focus-visible]:ring-2→ ❌ 无效,Tailwind 不处理该伪类的 arbitrary 形式 -
[&:hover]:bg-blue-500→ ❌ 不推荐,语义重复且可能和 JIT 的 hover 变体冲突
@apply 中不能用 Arbitrary Variants
@apply 是原子类拼接器,只认预设工具类,完全不解析方括号语法。下面这段会报错:
.my-card {
@apply [&>div]:p-4;
}
正确做法是:要么直接在 HTML 中使用 [&>div]:p-4,要么在 @layer utilities 中定义一个带 arbitrary variant 的新工具类:
立即学习“前端免费学习笔记(深入)”;
@layer utilities {
.child-div-p-4 {
& > div {
@apply p-4;
}
}
}
但注意:这种写法已脱离 arbitrary variants 本意,属于手写 CSS,不再享受 JIT 的自动类生成与 PurgeCSS 安全清理。
常见失效原因:DOM 层级与空格编码
最常遇到“写了没反应”,往往卡在这两点:
- 父容器里存在注释、文本节点或 wrapper 元素,导致
:nth-child计数错位 —— 检查渲染后的 DOM 结构,确认目标元素是否真是直系子元素 - 选择器中用了空格但没替换为
_,比如[&:nth-child(2)]:text-red-500合法,但[&:nth-child(2)]:text-red-500(中间有空格)会编译失败或静默忽略 -
[&:has(+.divider)]:mt-0在旧版 Tailwind(v3.3 以下)不支持:has(),需升级并确认配置中启用了 experimental features
Arbitrary Variants 的真正价值不在“能写多复杂”,而在于补足那些 Tailwind 原生变体覆盖不到的 DOM 关系表达——比如跨兄弟元素响应、深层嵌套条件、或需要 :has() 这类新特性的场景。一旦发现同一模式反复出现三次以上,就该考虑抽成组件或自定义指令,而不是靠一堆方括号硬撑。



















