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

ReactJS滚动高亮激活导航菜单及导航空间不足展示方案咨询

React 移动端导航栏(滚动高亮+溢出滚动)完整实现方案

1. 页面滚动时高亮当前激活导航菜单的实现

  • 首先给每个导航菜单对应的页面区块设置唯一的id属性,比如菜品分类对应#recommend、#hot等
  • 监听window的scroll事件,增加节流优化避免频繁触发回调,计算每个区块距离视口顶部的距离getBoundingClientRect().top
  • 当某个区块的top值小于等于导航栏的高度(可额外加10-20px偏移量避免判定误差),且区块底部距离视口顶部的距离大于导航栏高度时,就把当前区块对应的导航项设为激活状态
  • 激活状态通过自定义类名修改文字颜色、底部下划线等样式实现,同时支持点击导航项平滑滚动到对应区块
    核心实现代码如下:
import { useState, useEffect, useCallback } from 'react';

// 导航菜单配置,可根据业务需求修改
const navList = [
  { id: 'recommend', name: '推荐' },
  { id: 'hot', name: '热销' },
  { id: 'drink', name: '饮品' },
  { id: 'snack', name: '小吃' },
  { id: 'main', name: '主食' },
  { id: 'dessert', name: '甜点' }
];

const NavBar = () => {
  const [activeId, setActiveId] = useState('recommend');
  const NAV_HEIGHT = 50; // 导航栏固定高度,可根据实际样式调整

  // 节流函数,控制滚动事件触发频率
  const throttle = (func, delay) => {
    let timer = null;
    return function(...args) {
      if (!timer) {
        timer = setTimeout(() => {
          func.apply(this, args);
          timer = null;
        }, delay);
      }
    }
  };

  // 滚动监听逻辑,判定当前激活区块
  const handleScroll = useCallback(throttle(() => {
    for (const item of navList) {
      const element = document.getElementById(item.id);
      if (!element) continue;
      const rect = element.getBoundingClientRect();
      if (rect.top <= NAV_HEIGHT && rect.bottom > NAV_HEIGHT) {
        setActiveId(item.id);
        break;
      }
    }
  }, 100), []);

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

  // 点击导航项平滑滚动到对应区块
  const scrollToSection = (id) => {
    const element = document.getElementById(id);
    if (element) {
      const offsetTop = element.offsetTop - NAV_HEIGHT; // 减去导航高度避免内容被遮挡
      window.scrollTo({ top: offsetTop, behavior: 'smooth' });
    }
  };

  // 激活项自动滚动到导航栏可视区域
  useEffect(() => {
    const activeNav = document.querySelector(`.nav-item[data-id="${activeId}"]`);
    if (activeNav) {
      activeNav.scrollIntoView({
        behavior: 'smooth',
        block: 'nearest',
        inline: 'center'
      });
    }
  }, [activeId]);

  return (
    <nav className="nav-container">
      {navList.map(item => (
        <div
          key={item.id}
          data-id={item.id}
          className={`nav-item ${activeId === item.id ? 'active' : ''}`}
          onClick={() => scrollToSection(item.id)}
        >
          {item.name}
        </div>
      ))}
    </nav>
  )
};
export default NavBar;

2. 导航区域空间不足时完整展示所有选项的实现

核心通过CSS实现横向滚动效果,无需折叠为汉堡菜单,样式代码如下:

.nav-container {
  position: sticky;
  top: 0;
  height: 50px;
  z-index: 99;
  background: #fff;
  display: flex;
  /* 核心横向滚动配置 */
  overflow-x: auto;
  white-space: nowrap;
  /* 隐藏滚动条,兼容多浏览器 */
  -ms-overflow-style: none;
  scrollbar-width: none;
}
/* 隐藏Chrome/Safari等webkit内核浏览器的滚动条 */
.nav-container::-webkit-scrollbar {
  display: none;
}
.nav-item {
  padding: 0 16px;
  line-height: 50px;
  font-size: 14px;
  color: #333;
  flex-shrink: 0; /* 避免导航项被压缩 */
  cursor: pointer;
  position: relative;
}
.nav-item.active {
  color: #ff4d4f;
  font-weight: 500;
}
/* 激活项底部下划线 */
.nav-item.active::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 20px;
  height: 2px;
  background: #ff4d4f;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 14:06:03