旧版浏览器(Chrome 105以下、Firefox 120及更早、Safari 15.3及更早)因未实现:has()语法,在CSS解析阶段直接跳过整条规则,连声明都丢弃;document.querySelector('div:has(.child)')会抛DOMException,且CSS.supports('selector(:has(*))')存在假阳性,必须结合Computed面板验证真实生效。

因为浏览器压根没实现 :has() 语法,不是“不生效”,而是解析阶段直接跳过整条规则——连大括号里的声明都丢弃了。
Chrome 105 以下、Firefox 120 及更早、Safari 15.3 及更早都不认识 :has()
这些版本的 CSS 解析器在词法分析时遇到 :has(),会判为非法 token,整条规则静默失效。DevTools 的 Styles 面板里看不到它,控制台也不报错,容易误以为是选择器写错了。
-
document.querySelector('div:has(.child)')在 Firefox 120 或 Safari 15.3 中直接抛出DOMException: "is not a valid selector" - Safari ≤15.3 和多数安卓 WebView(如微信 X5 内核)完全不解析,
:has(+ .sibling)这类兄弟选择器更早失效 - CanIUse 标的“85% 全球支持”不反映真实业务场景——B 端系统、金融 App、企业内网仍大量跑在 Chrome 70–90 区间
CSS.supports('selector(:has(*))') 返回 true ≠ 真可用
这个检测在旧版 Chromium(Chrome 90–104)中存在假阳性:返回 true,但样式完全不渲染。它只说明语法被识别,不验证运行时执行能力。
- 别用
@supports selector(:has())包裹关键样式块——部分构建流程会把整个@supports块当作无效 CSS 删除 - 真正可靠的验证方式只有两个:
CSS.supports('selector(:has(div))')返回true,且目标父元素在 DevTools 的 Computed 面板中确实应用了该规则 - W3C nu validator 报
CSS: Parse Error: )是工具滞后,不是代码错误;加空格写成body:has( .modal)可绕过,但不影响浏览器行为
写了 :has() 却没反应?先排查这三件事
即使浏览器版本达标,:has() 也可能因写法或上下文失效。
立即学习“前端免费学习笔记(深入)”;
- 括号里用了不被允许的选择器:
div:has(::before)(伪元素非法)、a:has(:hover)(运行时状态无法静态判断)、section:has(:has(p))(嵌套:has()仅 Chrome 105+ 支持) - 子元素不可见:
:has()不匹配display: none或visibility: hidden的后代;用el.querySelector('.child')?.offsetParent !== null才能等价判断 - 父元素没稳定标识:JS 替代方案里依赖
div:nth-child(2)这类结构选择器,DOM 微调就断掉;必须用class="form-group"或id定位
最容易被忽略的是性能代价:哪怕语法合法,:has(p a) 这类深层后代匹配会触发显著重排,尤其在 Safari 和低端设备上,布局抖动比样式没生效更难定位。


















