:has() 可实现复选框选中时控制同父级兄弟或后代元素样式,但仅限同一父容器内,不支持跨父级、伪类链式调用及js动态变更监听,旧浏览器需js fallback。

复选框选中时让兄弟元素变灰不可用
直接用 :has() 配合 :checked 就能实现,但注意它只作用于**父容器内**的兄弟或后代元素,不能跨父级影响其他区域。比如一个 <label></label> 包裹 <input type="checkbox"> 和 <button></button>,选中后禁用按钮:
label:has(input:checked) button {
opacity: 0.5;
pointer-events: none;
}
常见错误是把 button 放在 label 外面——这时 :has(input:checked) 查不到它,样式不生效。必须保证目标元素和 input 在同一父容器下,或至少是它的后代。
多个复选框共同控制一个开关状态
想实现“任一复选框选中,就显示提示条”,用 :has() 很方便:
.container:has(input[type="checkbox"]:checked) .hint {
display: block;
}
但要注意:如果复选框初始未选中,.hint 必须默认 display: none;否则首次渲染时会闪一下。另外,:has() 不监听动态变更(如 JS 改 checked 属性),仅响应用户点击或原生表单交互。
-
:has()的选择器里不能写伪类链式调用,比如:has(input:checked:focus)是无效的 - Chrome 105+、Firefox 119+、Safari 15.4+ 支持;旧版 Safari 需加
-webkit-前缀且兼容性差 - 不要用
:has()替代 JS 控制复杂逻辑——它只适合简单显示/隐藏、启用/禁用类切换
用 :has() 实现“全选/反选”按钮联动
要让“全选”按钮根据子项状态自动更新文字或图标,得靠父容器判断子项是否全部选中。可惜 :has() 没有 :not(:has(...)) 这种“全未选中”的简洁写法,只能分两步:
.group:has(input:checked):not(:has(input:not(:checked))) .select-all-btn::after {
content: "✓ 全选";
}
.group:has(input:not(:checked)) .select-all-btn::after {
content: "○ 全选";
}
这里用了两个规则覆盖:第一个匹配“有选中且没有未选中”的情况(即全选),第二个只要存在未选项就生效。实际项目中更推荐用 JS 维护一个 data-all-checked 属性,再用 [data-all-checked] 选择器,避免 :has() 嵌套过深导致性能抖动。
IE 或旧浏览器 fallback 方案怎么写
:has() 在 IE 中完全不支持,连前缀都不行。如果必须兼容,得回退到 JS 监听 change 事件手动加 class:
document.querySelectorAll('input[type="checkbox"]').forEach(box => {
box.addEventListener('change', () => {
const group = box.closest('.group');
if (group) {
const allChecked = [...group.querySelectorAll('input[type="checkbox"]')]
.every(cb => cb.checked);
group.classList.toggle('all-checked', allChecked);
group.classList.toggle('some-checked', !allChecked && [...group.querySelectorAll('input[type="checkbox"]')].some(cb => cb.checked));
}
});
});
然后用 .group.all-checked 和 .group.some-checked 写 CSS。别指望纯 CSS fallback —— 没有 :has() 就真没等价替代,这是现代 CSS 的边界所在。
真正容易被忽略的是:即使写了 :has() 规则,也要检查父容器是否设置了 display: contents 或 display: none——前者会让 :has() 失效(因为子元素脱离文档流),后者会让整个块不可见,联动也就失去意义。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











