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

Next.js实现锚点链接跳转及激活状态高亮的方法

Next.js 锚点滚动与链接激活状态实现方案

前提准备

确保页面中每个需要跳转的目标区域都设置了匹配的id属性,比如链接指向#section1,对应区域就要写:

<section id="section1">...</section>

完整实现代码

在你的导航组件中添加状态管理和滚动监听逻辑,同时动态控制链接的激活样式:

'use client'; // Next.js 13+ App Router 需添加此指令,确保组件在客户端渲染

import { useState, useEffect } from 'react';
import Link from 'next/link';
import cn from 'classnames';

export default function Navbar() {
  // 替换成你实际的导航链接数组
  const navLinks = [
    { name: '首页', path: 'home' },
    { name: '关于我们', path: 'about' },
    { name: '服务', path: 'services' },
    { name: '联系我们', path: 'contact' }
  ];

  const [activePath, setActivePath] = useState('');

  useEffect(() => {
    const updateActiveLink = () => {
      navLinks.forEach((link) => {
        const section = document.getElementById(link.path);
        if (!section) return;

        const rect = section.getBoundingClientRect();
        // 判断元素是否进入视口(可根据需求调整阈值,这里设置为顶部距视口顶部≤100px且底部≥100px)
        const isActive = rect.top <= 100 && rect.bottom >= 100;
        if (isActive) setActivePath(link.path);
      });
    };

    // 初始加载时执行一次,设置默认激活项
    updateActiveLink();
    // 监听滚动事件更新激活状态
    window.addEventListener('scroll', updateActiveLink);
    // 组件卸载时移除监听
    return () => window.removeEventListener('scroll', updateActiveLink);
  }, [navLinks]);

  return (
    <ul className="font-medium flex flex-col p-4 md:p-0 mt-4 md:flex-row md:space-x-8 rtl:space-x-reverse md:mt-0 transition-all">
      {navLinks.map((link, index) => (
        <li key={index}>
          <Link
            href={`#${link.path}`}
            scroll={false} // 关闭Next.js默认滚动,改用自定义平滑滚动(可选)
            onClick={(e) => {
              e.preventDefault();
              const target = document.getElementById(link.path);
              if (target) {
                target.scrollIntoView({ behavior: 'smooth', block: 'start' });
                // 点击后直接设置激活状态
                setActivePath(link.path);
              }
            }}
            className={cn(
              "block py-2 px-3 text-white rounded md:bg-transparent md:text-blue-700 md:p-0 dark:text-white hover:dark:text-blue-500 transition-all",
              // 激活状态样式:这里示例为变色+下划线,可根据需求修改
              activePath === link.path && "md:text-blue-500 dark:text-blue-500 underline underline-offset-4"
            )}
            aria-current={activePath === link.path ? "page" : undefined}
          >
            {link.name}
          </Link>
        </li>
      ))}
    </ul>
  );
}

核心逻辑说明

  1. 状态管理:用activePath记录当前处于视口内的区域ID,以此控制链接的激活样式。
  2. 滚动监听:通过getBoundingClientRect()获取目标区域的位置,判断其是否进入视口,实时更新activePath。
  3. 平滑滚动:关闭Next.js默认滚动后,手动调用scrollIntoView实现平滑滚动,同时点击链接时直接设置激活状态。
  4. 样式控制:借助classnames工具动态拼接激活样式类,实现变色、下划线等视觉反馈。
  5. 可访问性:通过aria-current属性标记当前激活的链接,提升页面的无障碍体验。

如果不需要自定义平滑滚动,也可以保留Next.js默认的scroll={true},只需移除onClick里的自定义滚动逻辑即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 07:53:11