F10▸S001▸framer-motion
Smooth Scroll (Lenis)
平滑滾動
難度 ★★★★★標籤 滾動 · lenis · scrollTo3 min read
效果簡述
把整頁滾動換成 Lenis 的 RAF 平滑版本。重點是「真的需要嗎」—— 預設 原生滾動更快、更省電。Lenis 只是「同事跟主管都覺得很滑」時的好工具。
Lenis 平滑滾動 · duration 1.2
試試這兩個按鈕
Claude Code Prompt
參考:S001 smooth scroll 技術:lenis(單獨用,不要全站套,會跟其他 useScroll 打架) Demo 行為: - new Lenis() - requestAnimationFrame loop 呼叫 lenis.raf(time) - 提供 scrollTo(target) 按鈕做示範 - unmount 時 lenis.destroy() 限制: - 不要在 layout.tsx 全站啟用(會跟 F11 / F13 衝突) - 手機效能差,考慮關閉(lenis options: smoothTouch: false) - 含 sticky 區塊要小心,可能會卡
完整程式碼
'use client'
import Lenis from 'lenis'
import { useEffect, useRef } from 'react'
export function SmoothScrollLenis() {
const lenisRef = useRef<Lenis | null>(null)
useEffect(() => {
const lenis = new Lenis()
lenisRef.current = lenis
let raf = 0
function loop(t: number) {
lenis.raf(t)
raf = requestAnimationFrame(loop)
}
raf = requestAnimationFrame(loop)
return () => {
cancelAnimationFrame(raf)
lenis.destroy()
}
}, [])
function scrollTo(target: number) {
lenisRef.current?.scrollTo(target, { duration: 1.4 })
}
return (
<div className="flex gap-3">
<button onClick={() => scrollTo(0)}>到頂</button>
<button onClick={() => scrollTo(1200)}>到 1200px</button>
</div>
)
}何時用
- ✅ 作品集 / 品牌站(賣質感)
- ✅ 需要
scrollTo平滑跳轉(錨點) - ✅ 客戶指名要「絲滑」
何時別用
- ❌ 內容站 / 文件站(破壞讀者預期的滾動速度)
- ❌ 跟 useScroll/ScrollTrigger 大量並用(互打)
- ❌ 行動裝置為主(耗電、卡頓)
我踩過的坑
-
跟 useScroll 同時用會錯位:Lenis 改了真實 scroll 位置的更新 時機,framer-motion 的 useScroll 偶爾抓到舊值。解法:要嘛只用一個, 要嘛把 ScrollTrigger / framer-motion 的 scroll source 對齊到 Lenis。
-
destroy 漏掉切頁就壞:SPA 切頁但 RAF 還在跑,會吃 CPU。 一定要 cleanup
cancelAnimationFrame+lenis.destroy()。 -
手機效能差:smoothTouch 預設 false 是對的,別開。
相關效果
- F11 Scroll Progress Bar — 純 useScroll,搭得起來
- F13 Parallax Image — 同樣靠 scroll