在NextJS中阻止Fixed元素触发背景滚动的方法
解决Fixed组件滚动时背景滚动的问题
核心原因
这是浏览器的滚动穿透问题:当fixed定位的可滚动元素滚到边界后,继续滚动会触发底层页面的滚动。
解决方案
1. 动态控制body的滚动状态
在抽屉打开时给body添加overflow: hidden,关闭时移除,彻底禁止背景滚动,同时不影响遮罩层的点击交互。结合React的useEffect监听抽屉状态:
import { useEffect } from 'react'; import { useSelector, useDispatch } from 'react-redux'; import { selectMenu, toggleMenu } from '../path-to-your-redux-slice'; // 替换为你的redux slice路径 function Drawer() { const toggle = useSelector(selectMenu); const dispatch = useDispatch(); // 监听抽屉显示/隐藏,控制body滚动 useEffect(() => { if (toggle) { document.body.style.overflow = 'hidden'; } else { document.body.style.overflow = ''; } // 组件卸载时恢复body默认状态 return () => { document.body.style.overflow = ''; }; }, [toggle]); const handleOnClose = (e) => { if (e.target.id === "container") dispatch(toggleMenu(!toggle)); }; return ( <div id="container" onClick={handleOnClose} className={`md:hidden h-full w-full backdrop-blur-sm fixed ${!toggle && "hidden"}`} > <div className={`${toggle ? " translate-x-0" : "translate-x-full"} md:hidden fixed h-screen w-3/4 ease-in-out duration-300 bg-white z-50 bottom-0 top-0 right-0 flex flex-col px-4 py-3 space-y-5 shadow-2xl overflow-y-auto`} style={{ overscrollBehavior: 'contain' }} > <Link href="/" className="cursor-pointer flex px-2 space-x-4" onClick={() => dispatch(toggleMenu(!toggle))} > <HomeModernIcon className="h-6 w-6 text-black" /> <h1>Dashboard</h1> </Link> <div className=" h-[1px] w-full bg-gray-600" /> <Link href="/clients" className="cursor-pointer flex px-2 space-x-4" onClick={() => dispatch(toggleMenu(!toggle))} > <TruckIcon className="h-6 w-6 text-black" /> <h1>Clients</h1> </Link> <div className=" h-[1px] w-full bg-gray-600" /> <Link href="/employee" className="cursor-pointer flex px-2 space-x-4" onClick={() => dispatch(toggleMenu(!toggle))} > <PuzzlePieceIcon className="h-6 w-6 text-black" /> <h1>Employee</h1> </Link> <div className=" h-[1px] w-full bg-gray-600" /> <Link href="/services" className="cursor-pointer flex px-2 space-x-4" onClick={() => dispatch(toggleMenu(!toggle))} > <WrenchIcon className="h-6 w-6 text-black" /> <h1>Services</h1> </Link> </div> </div> ); }
2. 用CSS属性阻止滚动穿透
给抽屉的可滚动容器添加overscroll-behavior: contain,这个属性会阻止滚动事件传递到父元素,避免滚到底后触发背景滚动。
如果用Tailwind,可以先在tailwind.config.js中添加自定义工具类:
module.exports = { theme: { extend: { overscrollBehavior: { 'contain': 'contain', }, }, }, };
之后直接在抽屉容器上使用overscroll-contain类:
<div className={`... overflow-y-auto overscroll-contain`}>
3. 阻止滚动事件冒泡(可选)
如果前两种方法效果不佳,可以在抽屉的滚动事件中阻止冒泡:
const handleDrawerScroll = (e) => { e.stopPropagation(); }; // 在抽屉div上绑定事件 <div className={`... overflow-y-auto`} onScroll={handleDrawerScroll} >
关键说明
- 控制
body的overflow:hidden是最彻底的方案,既能禁止背景滚动,又不影响遮罩层的点击关闭功能。 overscroll-behavior-contain是现代浏览器原生支持的属性,无需修改body样式,适合仅需阻止滚动穿透的场景。
内容的提问来源于stack exchange,提问作者Mohammed Bekele
相关产品推荐
相关产品推荐

