Tailwind 默认不支持子元素状态驱动父元素样式,需启用 corePlugins.has 才能使用 has- 类名,其语法为 has-[&_selector]:utility,依赖 :has() 浏览器支持且有性能限制。

为什么直接写 .parent:hover .child 不行
因为 Tailwind 默认只生成原子类,:hover、:focus 等伪类都作用在**当前元素自身**上。你写 hover:opacity-80,生效的是「这个元素」悬停时变透明;它无法感知子元素是否被悬停,更不会因此去改父级样式。这是 CSS 层叠机制决定的——CSS 原生不支持“子元素状态驱动父元素样式”,直到 :has() 出现。
:has() 在 Tailwind 中怎么启用
Tailwind 3.3+ 原生支持 :has(),但默认关闭。必须手动开启,否则即使写了也编译不出对应 CSS:
- 打开
tailwind.config.js - 在
content同级添加:corePlugins: { <strong>preflight</strong>: true, <strong>has</strong>: true // ← 关键:必须显式设为 true } - 重启开发服务器(热更新不触发新插件加载)
没开这个开关,has-[&_input:focus]:border-blue-500 这类类名会被完全忽略,控制台无报错,但样式就是不出现——这是最常踩的坑。
实际怎么写 has- 类名:语法和常见模式
has- 是 Tailwind 的功能前缀,后面接的是「子选择器」,用 & 表示当前元素自身。括号里是完整的选择器字符串,必须合法、可解析:
立即学习“前端免费学习笔记(深入)”;
- 子元素聚焦时父边框变蓝:
has-[&_input:focus]:border-blue-500 - 子 checkbox 被勾选时父加背景:
has-[&_input[type=checkbox]:checked]:bg-green-50 - 子有错误消息时父标红:
has-[&_.error-message]:border-red-400 - 注意空格和引号:括号内不能换行,
type=checkbox不加引号;&_中的&是转义后的&,代表当前元素
浏览器兼容性要留意::has() 目前 Chrome 105+、Firefox 103+、Safari 15.4+ 支持,IE 和旧 Edge 完全不支持。如果项目需兼容 Safari 15.3 或更低,别用。
性能和可维护性提醒
:has() 是 CSS 中少有的「从右往左匹配失败后回溯」的选择器,浏览器引擎处理成本比普通选择器高。尤其嵌套深或频繁重绘时可能卡顿:
- 避免写
has-[&_div_&_span_&_button:hover]这种多层嵌套 - 不用
:has()替代 JS 控制逻辑——比如表单校验后动态加 class,比硬塞一堆has-[&_*.invalid]更可控 - Tailwind 的
has-类名最终生成的是标准 CSS:has()规则,所以调试时直接看 DevTools 里的 computed styles,别在 class 列表里找“父元素有没有被加上某个类”
真正要用好它,得接受一个事实:它不是万能补丁,而是给特定 DOM 结构(比如封装好的表单控件、卡片容器)提供一种声明式响应能力——前提是结构稳定、状态明确、目标浏览器可控。


















