firefox 121+ 默认支持 :has() 且行为与 chrome/safari 一致,旧版 firefox 和 ios 15.3 等不支持;应优先用事件监听(如 input blur、checkbox change)替代 mutationobserver 或 :has(),并确保基础样式降级。

:has() 在 Firefox 旧版本(
Firefox 120 及更早版本必须手动开启 layout.css.has-selector.enabled
即使你确认了选择器语法正确、DOM 结构合理,Firefox 120 及更早仍默认禁用 :has()。启用步骤很明确:
- 地址栏输入
about:config,搜索layout.css.has-selector.enabled - 双击将值设为
true(无需重启,刷新页面立即生效) - 注意:Firefox 121+ 已默认开启,但部分企业定制版或 ESR 分支可能被策略关闭,建议始终验证此项
⚠️ 这个设置只影响本地开发环境,**绝不能用于生产部署**——你无法要求用户手动改 about:config。
Chrome 105+/Safari 15.4+ 能用,但 Firefox 121+ 才真正稳定
Firefox 对 :has() 的支持分阶段:
- Firefox 103–120:实验性支持,
querySelectorAll(':has(*)')可能抛错,:has(> .child)等带关系符的写法匹配异常 - Firefox 121+:默认启用,与 Chrome/Safari 行为一致,包括
:has(+ .sibling)和:has(~ .any-later) - 旧版 Safari(如 iOS 15.3)仍完全不识别,
@supports selector(:has(*))自身也不被支持
所以如果你在 Firefox 120 测试时发现 form:has(input:invalid) 没反应,别调样式,先升级浏览器或换方案。
DMap GL地图JSAPI(dmapgl)开发指南。用于编写、审查、调试 DMap 地图 API 代码,涵盖地图初始化、覆盖物渲染、图层管理、事件处理、控件交互等任务。当用户提及 dmap、dmapgl、jsapi‑gl 或相关地图开发需求时自动触发。
JS 替代方案:监听关键状态,而非盲扫 DOM
依赖 MutationObserver 监听所有子节点变化是常见误区——开销大、易误触发、难以清理。真实项目应聚焦「你真正在意的状态」:
- 表单校验:监听
input的blur或change,用field.checkValidity()判断,再给field.closest('.form-group')加has-error类 - 卡片高亮:监听
checkbox的change,而非轮询document.querySelectorAll('.card') - 避免用
offsetParent === null判可见性——display: none的元素querySelector仍会返回,但不应触发父级样式
示例:精准响应 checkbox 状态
const toggleCardClass = (cb) => {
const card = cb.closest('.card');
if (!card) return;
card.classList.toggle('is-checked', cb.checked);
};
document.querySelectorAll('.card input[type="checkbox"]').forEach(cb => {
cb.addEventListener('change', () => toggleCardClass(cb));
});
结构前置比 JS 更轻量:后端或模板层加状态类
如果 DOM 是服务端渲染或静态生成的,最稳的方式是把判断逻辑提前:
- PHP/Node 模板中:
<div class="card <?= has_active_child($children) ? 'has-active' : '' ?>"> <li>React 中:用 <code>useEffect计算子项数量并更新 state,再传给 className - 避免在
:has()规则里写关键布局属性(如display: grid),否则老浏览器直接丢失结构——基础display: block必须无条件存在
真正容易被忽略的是::has() 的性能成本藏在重排里。一个含 50 个子项的列表,每帧执行 ul:has(li.active),滚动时帧率下降明显。结构前置或事件驱动,才是生产环境的底线。










