:has()无法实现抽屉菜单滚动锁定,因其不支持@media内使用、不能选择祖先元素、浏览器直接忽略overflow等样式变更;可靠方案是#menu-toggle:checked ~ body或html.is-drawer-open body配合JS切换类名。

:has() 无法实现抽屉菜单展开时的页面滚动锁定。 它既不能向上选择 body,也无法触发 overflow: hidden 这类影响盒模型与滚动行为的样式变更——浏览器会直接忽略此类尝试。
为什么 :has() 在滚动锁定场景中完全失效
你可能会写出类似这样的 CSS:
@media (max-width: 768px) {
body:has(#menu-toggle:checked) {
overflow: hidden;
}
}
但它不会生效,原因很实在:
-
:has()不允许出现在@media规则内部,Chrome 125+、Safari 17.5、Firefox 126 均明确不支持,整条规则被丢弃 -
:has()选择器本身不能作为“状态触发器”去修改祖先元素(如body)的overflow、position或尺寸属性 - 即使写成
html:has(#menu-toggle:checked) body,CSS 选择器语法也不允许这种跨层级的祖先匹配
真正能用的纯 CSS 滚动锁定方案只有两种
它们都绕开 :has(),靠 DOM 顺序和兄弟/相邻选择器驱动:
- 用
#menu-toggle:checked ~ body—— 要求是的**同级前驱节点**(即放在开始标签后、其他内容之前),且body必须设display: block(默认就是) - 用
html.is-drawer-open body—— 通过 JS 切换上的类名,CSS 完全解耦,无 DOM 位置依赖,推荐用于复杂项目
后者更健壮:document.documentElement.classList.toggle('is-drawer-open') 配合 .is-drawer-open body { overflow: hidden; },无兼容性风险,也避免了 body 内联样式污染。
transform: translateX() 抽屉 + 滚动锁定的最小可行结构
滚动锁定只是配套动作,抽屉本身必须用 transform 才能保证性能。关键点都在 DOM 和 class 上:
-
放在最开头,紧贴标签后 -
作为汉堡按钮,和遮罩层
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











