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

NextJS+TS+Tailwind:打开侧边栏时阻止页面跳转到顶部

解决侧边栏激活时背景页面固定且不跳顶的问题

你遇到的跳顶问题,根源是直接给内容容器加overflow-hidden时,浏览器会自动重置滚动位置。正确的做法应该是控制body元素的滚动行为,同时保存并恢复滚动位置,避免跳顶。

具体实现步骤:

  • 监听侧边栏的active状态变化
  • 激活时:给body添加禁止滚动的样式,并记录当前滚动的Y轴位置
  • 关闭时:移除body的禁止滚动样式,恢复之前记录的滚动位置

修改后的_app.tsx代码:

import Footer from '@/components/footer';
import Navbar from '@/components/navbar';
import '@/styles/globals.css';
import type { AppProps } from 'next/app';
import { Inter } from 'next/font/google';
import { useState, useEffect } from 'react';

const inter = Inter({ subsets: ['latin'] });

export default function App({ Component, pageProps }: AppProps) {
  const [active, setActive] = useState(false);
  const [showSearch, setShowSearch] = useState(false);
  const [searchText, setSearchText] = useState('');
  // 保存滚动位置
  const [scrollPosition, setScrollPosition] = useState(0);

  const handleClick = () => {
    setActive(!active);
  };

  const sideClick = () => {
    setActive(false);
  };

  const searchClick = () => {
    setShowSearch(!showSearch);
  };

  const clearSearch = () => {
    setSearchText('');
  };

  useEffect(() => {
    if (active) {
      // 记录当前滚动位置
      setScrollPosition(window.scrollY);
      // 给body设置禁止滚动的样式,同时固定当前位置
      document.body.style.overflow = 'hidden';
      document.body.style.position = 'fixed';
      document.body.style.top = `-${scrollPosition}px`;
      document.body.style.width = '100%';
    } else {
      // 恢复body默认样式
      document.body.style.overflow = '';
      document.body.style.position = '';
      document.body.style.top = '';
      // 回到之前的滚动位置
      window.scrollTo(0, scrollPosition);
    }

    // 组件卸载时确保body样式恢复正常
    return () => {
      document.body.style.overflow = '';
      document.body.style.position = '';
      document.body.style.top = '';
    };
  }, [active]);

  return (
    <div className="flex flex-col h-screen">
      <div className="fixed top-0 z-50 w-full">
        <Navbar
          active={active}
          handleClick={handleClick}
          sideClick={sideClick}
          showSearch={showSearch}
          searchClick={searchClick}
          searchText={searchText}
          clearSearch={clearSearch}
        />
      </div>
      <div>
        <div className="max-w-[1372px] mt-[42px] md:mt-[48px] grow mx-auto justify-center">
          <Component {...pageProps} />
        </div>
        <div className="w-full">
          <Footer />
        </div>
      </div>
    </div>
  );
}

关键说明:

  • 通过useEffect监听active状态变化,在侧边栏切换时操作body样式
  • 激活时用position: fixed配合top值固定页面位置,同时禁用滚动,避免浏览器自动跳顶
  • 关闭时恢复body默认样式,并通过window.scrollTo回到之前记录的滚动位置
  • 卸载清理函数确保页面切换时body样式不会被异常保留

内容的提问来源于stack exchange,提问作者Casualzach

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 10:52:39