Frontend Lab
← 回到所有模式
PC05🧭 Navigation · 導航目錄

Scrollspy

滾動目錄

難度 ★★★★★標籤 scrollspy · IO · 目錄3 min read

模式簡述

Scrollspy:長文章右側目錄自動高亮當前段落。文件站、blog 必備。用 IntersectionObserver 實作。

前言

假內容假內容假內容⋯

安裝

假內容假內容假內容⋯

API

假內容假內容假內容⋯

進階

假內容假內容假內容⋯

FAQ

假內容假內容假內容⋯

頂部|第一節 active

Claude Code Prompt

💬 Claude Code Prompt
參考:PC05 scrollspy
組件:Scrollspy.tsx

Scrollspy:長文章右側目錄自動高亮當前段落。文件站、blog 必備。用 IntersectionObserver 實作。

限制:
- IO threshold 設錯
- 多個 section 同時可見
- 忘了平滑捲動

完整程式碼

Scrollspy.tsx
"use client";
import { useEffect, useState } from "react";
import { cn } from "@/lib/utils";

type State = "top" | "middle" | "bottom";

const SECTIONS = ["前言", "安裝", "API", "進階", "FAQ"];

export function Scrollspy({ state = "top" }: { state?: State }) {
const activeIdx = state === "top" ? 0 : state === "middle" ? 2 : SECTIONS.length - 1;
const [active, setActive] = useState(activeIdx);
useEffect(() => setActive(activeIdx), [activeIdx]);

return (
  <div className="grid w-full max-w-md grid-cols-[140px_1fr] gap-4">
    <aside className="space-y-0.5 self-start border-l border-border pl-3">
      {SECTIONS.map((s, i) => (
        <button
          key={s}
          onClick={() => setActive(i)}
          className={cn(
            "block w-full text-left text-xs transition",
            i === active
              ? "border-l-2 border-lab-accent -ml-[13px] pl-3 text-lab-accent"
              : "text-muted-foreground hover:text-foreground",
          )}
        >
          {s}
        </button>
      ))}
    </aside>
    <div className="space-y-3 rounded-lg border border-border bg-background/30 p-3">
      {SECTIONS.map((s, i) => (
        <div
          key={s}
          className={cn(
            "rounded-md px-3 py-2 text-xs transition",
            i === active ? "bg-lab-accent/10 ring-1 ring-lab-accent/30" : "bg-background/40",
          )}
        >
          <p className="font-medium text-foreground">{s}</p>
          <p className="mt-1 text-muted-foreground">假內容假內容假內容⋯</p>
        </div>
      ))}
    </div>
  </div>
);
}

何時用

  • ✅ 長篇文件、API reference
  • ✅ 技術 blog 文章
  • ✅ 教學內容章節導航

何時別用

  • ❌ 短文章 < 3 段(沒必要)
  • ❌ 純圖片或非文字內容
  • ❌ 手機端(沒空間放側欄)

我踩過的坑

  1. IO threshold 設錯:0 會在剛進視口就觸發,0.5 才合理。

  2. 多個 section 同時可見:取最頂部那個為 active,不是隨便挑一個。

  3. 忘了平滑捲動:點目錄要 smooth scroll 而不是瞬間跳。css scroll-behavior: smooth。

相關模式

  • PC02
  • PC04

搜尋

按 ⌘K 隨時開啟