如何阻止全屏菜单激活时页面滚动?现有CSS方案存在异常
解决全屏菜单激活后页面仍可滚动的问题
这问题我之前做项目时也踩过坑,直接给body,html加overflow: hidden确实会把页面本身的滚动功能锁死,太一刀切了。这里有几个更灵活的方案,你可以根据自己的场景选择:
方案一:通过类切换动态锁定页面滚动
核心思路是只在菜单激活时给页面添加滚动锁定样式,平时保持正常滚动。
- 先写好CSS样式:
/* 菜单激活时的页面锁定样式 */ .menu-active body, .menu-active html { overflow: hidden; max-height: 100vh; /* 用vh更可靠,避免父元素高度影响 */ } /* 可选:防止加overflow:hidden后页面跳回顶部 */ .menu-active body { position: fixed; width: 100%; }
- 用JS控制类的添加和移除:
let scrollPosition = 0; // 打开菜单时锁定滚动 function openFullscreenMenu() { // 记录当前滚动位置 scrollPosition = window.pageYOffset || document.documentElement.scrollTop; document.documentElement.classList.add('menu-active'); // 把页面固定在当前位置,避免跳顶 document.body.style.top = `-${scrollPosition}px`; } // 关闭菜单时恢复滚动 function closeFullscreenMenu() { document.documentElement.classList.remove('menu-active'); // 恢复之前的滚动位置 window.scrollTo(0, scrollPosition); document.body.style.top = ''; }
这个方案兼容性好,而且只在需要的时候锁滚动,不影响页面正常状态。
方案二:用fixed定位的菜单容器拦截滚动
如果不想修改body的样式,可以让全屏菜单本身占满整个视口,并且用fixed定位覆盖在页面上方,同时给菜单内部加滚动(如果菜单内容过多的话)。
CSS示例:
.fullscreen-menu { position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; background-color: #fff; /* 背景色覆盖页面 */ overflow-y: auto; /* 菜单内容超过视口时内部滚动 */ z-index: 9999; /* 确保在页面最上层 */ }
这种方式下,用户点击或滚动时只会触发菜单容器的交互,背后的页面因为被fixed菜单完全覆盖,自然没法滚动。好处是不用修改body的滚动属性,也不会有页面跳顶的问题。
方案三:用JS监听滚动事件并阻止默认行为
如果需要更精细的控制(比如菜单内部可以滚动,但页面不行),可以通过监听滚动/触摸事件,在菜单激活时阻止页面的滚动行为。
JS示例:
let isMenuActive = false; const menuContainer = document.querySelector('.fullscreen-menu'); function openMenu() { isMenuActive = true; // 添加滚动监听 document.addEventListener('wheel', preventPageScroll, { passive: false }); document.addEventListener('touchmove', preventPageScroll, { passive: false }); } function closeMenu() { isMenuActive = false; // 移除监听 document.removeEventListener('wheel', preventPageScroll); document.removeEventListener('touchmove', preventPageScroll); } function preventPageScroll(e) { // 只有当滚动目标不是菜单容器时,才阻止页面滚动 if (isMenuActive && !menuContainer.contains(e.target)) { e.preventDefault(); } }
注意:移动端要设置{ passive: false }才能正确阻止touchmove事件的默认行为,否则部分浏览器会忽略e.preventDefault()。
内容的提问来源于stack exchange,提问作者dizzierhys
相关产品推荐
相关产品推荐

