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

Next.js+react-scroll滚动到底部时如何设置最后一个section为激活状态?

React Scroll滚动到底部时激活链接不更新的问题解决

问题

用Next.js搭配react-scroll做的项目,粘性导航栏的激活链接会跟着视口里的section自动切换,但滚到页面底部时,激活状态停在section4,不会切到最后一个section7。已经开了spy={true}和smooth={true},所有section高度固定,滚动也流畅,就是最后一个section的激活状态触发不了。

复现代码

"use client"

import { Link, Element } from "react-scroll"

export default function Home() {
  return (
    <div>
      <div className="flex gap-2 items-center justify-center h-10 w-full bg-white sticky top-0">
        {Array.from({ length: 8 }).map((i, index) => (
          <Link
            key={index}
            to={`section${index}`}
            spy={true}
            smooth={true}
            className="[&.active]:text-amber-500"
          >
            to section {index}
          </Link>
        ))}
      </div>

      {Array.from({ length: 8 }).map((i, index) => (
        <Element
          key={index}
          name={`section${index}`}
          className="h-56 w-full bg-amber-100 mb-2"
        >
          section {index}
        </Element>
      ))}
    </div>
  )
}

解决方法

1. 调整react-scroll的激活阈值

react-scroll默认的spy判断逻辑比较严格,最后一个section可能因为没完全占满视口顶部而不触发激活。给<Link>加个threshold参数,降低激活所需的可见比例:

<Link
  key={index}
  to={`section${index}`}
  spy={true}
  smooth={true}
  threshold={0.1} // 元素可见10%就激活对应链接
  className="[&.active]:text-amber-500"
>
  to section {index}
</Link>

也可以试试offset={-10},调整滚动偏移量,让滚动到接近底部时提前触发激活。

2. 自定义滚动监听逻辑

如果上面的方法没用,就自己写滚动监听,手动判断最后一个section的可见状态:

"use client"

import { Link, Element } from "react-scroll"
import { useEffect, useState } from "react"

export default function Home() {
  const [activeSection, setActiveSection] = useState("section0")

  useEffect(() => {
    const handleScroll = () => {
      const sections = document.querySelectorAll("[data-scroll-id]")
      const lastSection = sections[sections.length - 1]
      const lastRect = lastSection.getBoundingClientRect()
      
      // 检测是否滚动到页面底部,同时最后一个section可见
      const isAtBottom = window.innerHeight + window.scrollY >= document.body.offsetHeight - 10
      if (isAtBottom && lastRect.top <= window.innerHeight) {
        setActiveSection(lastSection.getAttribute("data-scroll-id")!)
        return
      }

      // 处理其他section的激活
      sections.forEach(section => {
        const rect = section.getBoundingClientRect()
        // 100是导航栏的高度,根据自己的导航栏高度调整
        if (rect.top <= 100 && rect.bottom >= 100) {
          setActiveSection(section.getAttribute("data-scroll-id")!)
        }
      })
    }

    window.addEventListener("scroll", handleScroll)
    return () => window.removeEventListener("scroll", handleScroll)
  }, [])

  return (
    <div>
      <div className="flex gap-2 items-center justify-center h-10 w-full bg-white sticky top-0">
        {Array.from({ length: 8 }).map((i, index) => (
          <Link
            key={index}
            to={`section${index}`}
            spy={false} // 关掉默认spy,用自定义逻辑
            smooth={true}
            className={`${activeSection === `section${index}` ? 'text-amber-500' : ''}`}
          >
            to section {index}
          </Link>
        ))}
      </div>

      {Array.from({ length: 8 }).map((i, index) => (
        <Element
          key={index}
          name={`section${index}`}
          data-scroll-id={`section${index}`}
          className="h-56 w-full bg-amber-100 mb-2"
        >
          section {index}
        </Element>
      ))}
    </div>
  )
}

3. 给最后一个section加额外空间

如果最后一个section高度不够,给它加个底部内边距或者调高高度,让它能被react-scroll的spy检测到:

{Array.from({ length: 8 }).map((i, index) => (
  <Element
    key={index}
    name={`section${index}`}
    className={`h-56 w-full bg-amber-100 mb-2 ${index === 7 ? 'pb-16' : ''}`}
  >
    section {index}
  </Element>
))}

内容的提问来源于stack exchange,提问作者Tareq Al Mozayek

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 22:07:06