G01▸S101▸gsap
Pin Section + Scrub
釘住區塊 + 滾動驅動
難度 ★★★★★標籤 scrollTrigger · pin · scrub3 min read
效果簡述
GSAP ScrollTrigger 的招牌:區塊滾到頂端時釘住,動畫被滾動進度驅動。
做 product walkthrough、scrollytelling 必備。Framer 也能做但語法繁瑣,
GSAP 一行 pin: true + scrub: true 比較直覺。
↓ 滾我 · scrub: 1
釘住的我
Claude Code Prompt
參考:S101 pin section + scrub
技術:gsap + ScrollTrigger (pin / scrub)
具體行為:
- gsap.registerPlugin(ScrollTrigger)
- 用 gsap.context 包,return ctx.revert() cleanup
- gsap.to(target, { ...動畫, scrollTrigger: { trigger, start: 'top top', end: '+=600', pin: true, scrub: 0.5 } })
- scrub 給數字(0.3~0.8)比 true 更自然,會有微微緩衝
- end 用 '+=px' 而不是寫死位置
限制:
- 父層別有 overflow: hidden(會破壞 pin)
- 一個頁面 pin 區塊 < 3 個(否則跟使用者打架)
- mobile 改 scrub: true(少一個小數值平滑,反而更穩)完整程式碼
'use client'
import gsap from 'gsap'
import { ScrollTrigger } from 'gsap/ScrollTrigger'
import { useEffect, useRef } from 'react'
export function PinSectionScrub() {
const ref = useRef<HTMLDivElement>(null)
useEffect(() => {
gsap.registerPlugin(ScrollTrigger)
const ctx = gsap.context(() => {
gsap.to('.target', {
rotate: 90,
scale: 1.3,
ease: 'none',
scrollTrigger: {
trigger: ref.current,
start: 'top top',
end: '+=600',
pin: true,
scrub: 0.5,
},
})
}, ref)
return () => ctx.revert()
}, [])
return (
<section ref={ref} className="h-screen">
<div className="target h-32 w-32 bg-orange-600" />
</section>
)
}何時用
- ✅ 產品 walkthrough(每滾一段釋出一個 feature)
- ✅ 案例 reveal(圖被釘住,文字滾過)
- ✅ Long-form scrollytelling
何時別用
- ❌ 純文字內容站(破壞閱讀節奏)
- ❌ 一頁多個 pin(互相干擾)
- ❌ 父層 overflow-hidden 或 transform 的容器內
我踩過的坑
-
沒 ctx.revert() 切頁殘留:ScrollTrigger 會留在 document 上。 一定要用
gsap.context()+ctx.revert()。 -
scrub: true太敏感:滾動每一格立即同步,看起來抖。改成scrub: 0.3~0.8數字模式,有微緩衝更舒服。 -
end 寫死位置遲早出問題:響應式高度會變。用
'+=600'相對距離 比較穩。
相關效果
- G02 Horizontal Scroll — 同樣 pin + scrub 機制
- F14 Sticky Section — 純 CSS 簡化版