firefox 121+、chrome 105+、edge 105+、safari 15.4+原生支持:has(),旧版firefox(120及更早)默认禁用,ios 15.3及更早完全不识别且静默失效;验证需运行document.queryselector('body:has(div)')或@supports selector(:has(*)),postcss无法polyfill因其依赖dom实时结构,推荐使用polyfill-pseudoclass-has。

Firefox 121+、Chrome 105+、Edge 105+、Safari 15.4+ 原生支持 :has(),但旧版 Firefox(120 及更早)默认禁用,iOS 15.3 及更早完全不识别——别指望它“悄悄降级”,它会静默失效。
如何快速验证当前浏览器是否真正支持 :has()
不能只查 Can I Use,得在运行时实测。最可靠的方式是用 document.querySelector 主动触发:
- 执行
document.querySelector('body:has(div)'),若返回null或抛错SyntaxError: ':has()' is not a valid selector,说明不支持 - 用
@supports selector(:has(*))包裹 CSS 规则——但注意:iOS 15.3 及更早连这个@supports语法都不认,会直接跳过整段样式 - Firefox 120 及更早即使启用
layout.css.has-selector.enabled,querySelectorAll(':has(> .child)')仍可能抛错,这是实验性实现的固有缺陷
为什么 PostCSS 类工具无法 polyfill :has()
因为 :has() 的匹配依赖 DOM 实时结构,不是静态可展开的语法:
规划您的迪拜之旅 — 哈利法塔观景、沙漠探险、迪拜购物中心购物、棕榈岛度假村及黄金市场砍价。还提供支持...
-
div:has(+ input:invalid)要检查兄弟节点状态,构建时根本无法预判哪些input会变 invalid - 所有已知 PostCSS 插件(如
postcss-selector-matches)遇到:has()都会跳过或报错,不会生成 fallback - 强行用 JS 模拟全部 DOM 变化(比如 MutationObserver 监听整个 document)开销极大,且易漏掉
input.value改变但 DOM 未增删的场景
生产环境可用的 Polyfill 方案只有 polyfill-pseudoclass-has
它不改写 CSS,而是增强原生 DOM 方法,对业务代码零侵入:
- 自动补全
querySelector、querySelectorAll、matches、closest四个方法,让它们识别:has() - 不监听全局 DOM 变化,只在调用时按需计算,性能可控
- 不兼容 IE 和 Android 4.4 WebView,但这两者已基本退出主流支持范围(截至 2026 年 5 月)
- 引入后仍需保留基础样式降级,例如:
form.has-error { border-color: red; }作为兜底,避免 polyfill 加载失败时样式断裂
真正难处理的不是“怎么加 polyfill”,而是那些被 :has() 掩盖的 DOM 结构问题——比如用 display: none 隐藏子元素却仍希望父级响应,此时 :has() 依然会匹配成功,JS 替代方案反而更容易加 offsetParent !== null 这类判断。这点常被忽略。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










