You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NextJS单页应用:如何仅在移动端设置body样式避免桌面滚动冻结?

解决NextJS移动端导航仅在移动端控制body滚动的问题

你的问题出在当前代码不区分设备类型,只要导航菜单状态变化就修改body的className,导致桌面模式下也会触发overflow:hidden,进而无法滚动。下面提供两种实用解决方案:

方案一:JS中判断设备宽度,仅在移动端修改body类

通过监听窗口宽度,动态判断是否为移动端,只在移动端时修改body的类名:

  1. 新增状态跟踪设备类型:
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);
}, []);
  1. 修改原导航逻辑,仅在移动端操作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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 11:56:34