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

如何正确使用window.scrollY实现滚动超50px后固定头部导航

问题原因
  • 初始状态将direction默认值设为"up",页面首次加载就会匹配固定导航样式,导致导航直接置顶遮挡顶部提示条
  • 滚动监听未设置50px触发阈值,页面只要产生滚动就会切换导航样式,和顶部提示条产生层级冲突
  • 用普通变量存储oldScrollY会在组件重渲染时被重置,容易出现滚动方向判断错误
  • 试图通过调整z-index解决遮挡属于治标不治本,没有从定位逻辑上规避两个元素的重叠场景
修复实现
  • 将direction初始值设为null,页面加载初始阶段不挂载任何固定/透明导航的特殊类,导航保持默认文档流定位,自然排在顶部提示条下方,不会产生遮挡
  • 用useRef存储上一次滚动位置,避免组件重渲染导致变量值重置
  • 在滚动监听逻辑中增加阈值判断:只有页面滚动高度超过50px时才执行滚动方向判断,滚动高度回到50px以内时清空方向状态,导航回归默认位置
  • 类名绑定统一处理,避免多个属性同时设置产生样式冲突
import { useState, useEffect, useRef } from 'react';

const Navbar = () => {
  const [direction, setDirection] = useState(null);
  const lastScrollY = useRef(0);

  const handleScroll = () => {
    const currentScrollY = window.scrollY;
    // 未达滚动阈值时重置状态,导航回到默认静态位置
    if (currentScrollY <= 50) {
      setDirection(null);
      lastScrollY.current = currentScrollY;
      return;
    }
    // 超过阈值后判断滚动方向
    setDirection(currentScrollY > lastScrollY.current ? 'down' : 'up');
    lastScrollY.current = currentScrollY;
  };

  useEffect(() => {
    window.addEventListener('scroll', handleScroll, { passive: true });
    return () => window.removeEventListener('scroll', handleScroll);
  }, []);

  // 拼接导航类名
  const navClassName = [
    styles.navbar,
    direction === 'up' ? styles.fixed_navbar : '',
    direction === 'down' ? styles.transparent__nav : ''
  ].filter(Boolean).join(' ');

  return (
    <header className={navClassName}>
      {/* 导航内部内容 */}
    </header>
  );
};
样式配置说明
  • 只需要给styles.fixed_navbar设置z-index: 999即可,顶部白色提示条不需要调整z-index:滚动高度在50px以内时,导航是普通文档流元素,不会和提示条重叠;滚动高度超过50px后,顶部提示条已经被滚动到视口外,不存在提示条遮挡导航菜单、链接无法点击的问题
  • 可以给导航加transition: all 0.3s ease过渡属性,样式切换时更顺滑
  • 如果需要向下滚动时完全隐藏导航,可以在styles.transparent__nav中加transform: translateY(-100%),比单纯设置透明的交互体验更好

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 19:39:12