Frontend Lab
← 回到所有模式
PG08📐 Layout · 版型滾動

Sticky Scroll Sections

Apple 黏滯滾動

難度 ★★★★標籤 apple · scrollytelling · sticky3 min read

模式簡述

Sticky Scroll:左側捲動切章、右側對應視覺 sticky。apple.com 產品故事頁標配。scrollytelling 經典做法。

01
區段 1|第一段 active

Claude Code Prompt

💬 Claude Code Prompt
參考:PG08 sticky-scroll
組件:StickyScroll.tsx

Sticky Scroll:左側捲動切章、右側對應視覺 sticky。apple.com 產品故事頁標配。scrollytelling 經典做法。

限制:
- sticky 沒設 top
- 右側視覺切換太突兀
- 手機 fallback 沒做

完整程式碼

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

type State = "step-1" | "step-2" | "step-3";

const STEPS = [
{ title: "捕捉", desc: "把你看到的好元件存起來。", color: "from-orange-400 to-rose-600" },
{ title: "拆解", desc: "拆成 props、狀態、邊界,寫進 MDX。", color: "from-emerald-400 to-teal-600" },
{ title: "重組", desc: "下一個專案直接整段貼進去。", color: "from-blue-400 to-violet-600" },
];

export function StickyScroll({ state = "step-1" }: { state?: State }) {
const idx = state === "step-2" ? 1 : state === "step-3" ? 2 : 0;
const [active, setActive] = useState(idx);
useEffect(() => setActive(idx), [idx]);

return (
  <div className="grid w-full max-w-2xl grid-cols-2 gap-5">
    <div className="space-y-3">
      {STEPS.map((s, i) => (
        <button
          key={i}
          onClick={() => setActive(i)}
          className={cn(
            "block w-full rounded-lg border p-3 text-left transition-all",
            i === active
              ? "border-lab-accent bg-lab-accent/5"
              : "border-border bg-background/30 opacity-50 hover:opacity-80",
          )}
        >
          <p className="font-mono text-[10px] text-muted-foreground">0{i + 1}</p>
          <p className="mt-0.5 text-sm font-medium">{s.title}</p>
          <p className="mt-1 text-[11px] text-muted-foreground">{s.desc}</p>
        </button>
      ))}
    </div>
    <div className="sticky top-0">
      <div
        className={cn(
          "grid aspect-square place-items-center rounded-xl bg-gradient-to-br transition-all duration-500",
          STEPS[active].color,
        )}
      >
        <span className="font-mono text-5xl text-white/80">0{active + 1}</span>
      </div>
    </div>
  </div>
);
}

何時用

  • ✅ 產品故事、功能介紹的長頁
  • ✅ scrollytelling 報導
  • ✅ 需要分步引導但又不想 break flow

何時別用

  • ❌ 手機端(會壓住關鍵內容)
  • ❌ 資訊密度高(每段太多字會擠)
  • ❌ 資訊型內容(讀者只想快速看完)

我踩過的坑

  1. sticky 沒設 top:黏不住直接跟著捲走。要 top-0 或 top-【navbar高度】

  2. 右側視覺切換太突兀:用 cross-fade 比直接 swap 順。

  3. 手機 fallback 沒做:手機應該垂直堆疊,圖在文上面。

相關模式

  • PG09
  • PC05

搜尋

按 ⌘K 隨時開啟