G04▸S104▸gsap
Scrollytelling
滾動敘事
難度 ★★★★★標籤 scrollTrigger · storytelling · sticky3 min read
效果簡述
左/上方 sticky 視覺、右/下方文字章節滾動。滾到不同章節時,視覺 換內容。是 NYT、Bloomberg、Pudding 那種長篇報導的核心招式。
🎨
第 1 章
設計階段 — 滾到這時上方圖示換
第 2 章
開發階段 — 滾到這時上方圖示換
第 3 章
上線階段 — 滾到這時上方圖示換
Claude Code Prompt
參考:S104 scrollytelling
技術:sticky 視覺 + ScrollTrigger onToggle 偵測當前章節
具體行為:
- 左欄(或上方)sticky top-0,放圖 / 數據 / 視覺
- 右欄(或下方)為章節文字
- gsap.utils.toArray('.chapter').forEach((el, i) => ScrollTrigger.create({ trigger: el, start: 'top 60%', end: 'bottom 60%', onToggle: ({ isActive }) => isActive && setStep(i) }))
- step 變動時切換視覺內容
限制:
- 章節 < 6 個(多了使用者會迷失)
- 視覺切換用 fade,不要硬切
- 行動上 sticky 上方視覺 + 內容下方滾比較自然完整程式碼
'use client'
import gsap from 'gsap'
import { ScrollTrigger } from 'gsap/ScrollTrigger'
import { useEffect, useRef, useState } from 'react'
export function Scrollytelling() {
const [step, setStep] = useState(0)
const root = useRef<HTMLDivElement>(null)
useEffect(() => {
gsap.registerPlugin(ScrollTrigger)
const ctx = gsap.context(() => {
gsap.utils.toArray<HTMLElement>('.chapter').forEach((el, i) => {
ScrollTrigger.create({
trigger: el,
start: 'top 60%',
end: 'bottom 60%',
onToggle: ({ isActive }) => isActive && setStep(i),
})
})
}, root)
return () => ctx.revert()
}, [])
return (
<section ref={root} className="grid grid-cols-2 gap-8">
<div className="sticky top-0 h-screen">{/* 視覺,根據 step 切換 */}</div>
<div className="space-y-[60vh]">
<div className="chapter">章節 1</div>
<div className="chapter">章節 2</div>
<div className="chapter">章節 3</div>
</div>
</section>
)
}何時用
- ✅ 長篇報導 / 案例研究
- ✅ 產品操作說明(每步配視覺)
- ✅ 數據敘事(地圖、圖表逐步揭露)
何時別用
- ❌ 一般行銷頁(多到難駕馭)
- ❌ 章節彼此沒關聯(拆成短篇還比較好)
- ❌ SEO 重要 + 行動使用者多
我踩過的坑
-
onToggle 切太快:start/end 區間重疊時,兩個章節都 active, step 跳來跳去。一定要把區間設成不重疊。
-
手機 sticky 高度問題:100vh sticky 上方時內容看不到。 mobile 用 50vh 上方視覺 + 下方滾比較合理。
-
章節切換沒過渡:onToggle 直接 setState 視覺硬切。在視覺 元件加 fade 過渡或 motion 過場。
相關效果
- G01 Pin Section + Scrub — 純 pin
- G03 Reveal on Scrub — 滾動觸發進場