NextJS单页应用:如何仅在移动端设置body样式避免桌面滚动冻结?
解决NextJS移动端导航仅在移动端控制body滚动的问题
你的问题出在当前代码不区分设备类型,只要导航菜单状态变化就修改body的className,导致桌面模式下也会触发overflow:hidden,进而无法滚动。下面提供两种实用解决方案:
方案一:JS中判断设备宽度,仅在移动端修改body类
通过监听窗口宽度,动态判断是否为移动端,只在移动端时修改body的类名:
- 新增状态跟踪设备类型:
const [ navbarOpen, setNavbarOpen ] = useState(false); const ref = useRef(); // 新增状态:是否为移动端 const [isMobile, setIsMobile] = useState(false); // 监听窗口尺寸变化,更新移动端状态 useEffect(() => { const checkDevice = () => { // 可根据需求调整移动端阈值(比如768px) setIsMobile(window.innerWidth < 768); }; // 初始化检查 checkDevice(); // 添加resize监听 window.addEventListener('resize', checkDevice); // 组件卸载时移除监听 return () => window.removeEventListener('resize', checkDevice); }, []);
- 修改原导航逻辑,仅在移动端操作body类:
useEffect(() => { const handler = (e) => { if (navbarOpen && ref.current && !ref.current.contains(e.target)) { setNavbarOpen(false); } }; // 仅在移动端时修改body类 if (isMobile) { document.body.className = navbarOpen ? '' : 'mobile-nav-active'; } else { // 桌面模式下主动移除类,避免残留影响 document.body.className = document.body.className.replace('mobile-nav-active', '').trim(); } // 添加点击事件监听(原代码遗漏了移除逻辑,补上避免内存泄漏) document.addEventListener('mousedown', handler); return () => document.removeEventListener('mousedown', handler); }, [navbarOpen, isMobile]);
方案二:CSS媒体查询控制样式(更简洁)
不需要修改JS逻辑,直接通过CSS媒体查询,让mobile-nav-active类仅在移动端生效:
修改你的CSS代码:
/* 仅在移动端(宽度≤767px)应用overflow:hidden */ @media (max-width: 767px) { .mobile-nav-active { overflow: hidden; } }
这样即使桌面模式下body被添加了mobile-nav-active类,也不会触发overflow:hidden,完全不影响滚动。
两种方案任选即可:方案一更严谨,不会给桌面模式的body添加多余类;方案二更简洁,无需额外JS逻辑。
内容的提问来源于stack exchange,提问作者Maicmi
相关产品推荐
相关产品推荐

