在 React 專案加動畫,常見的選擇有三個套件:Motion(前身為 Framer Motion)、GSAP 與 React Spring。三者都能做出同樣的淡入、位移與捲動效果,差別在 API 的寫法、授權條款,以及和 Next.js App Router 搭配時要注意的地方。這篇整理三者的事實資料,再說明動畫元件庫在選型裡的位置。
授權與版本資訊查核日期:2026-10-14。
先確認:需要 JavaScript 動畫套件嗎
hover 變色、展開收合、進場淡入這類固定的狀態轉換,CSS transition 與 @keyframes 就足夠,Tailwind 的 transition-*、animate-* 與 motion-reduce: 前綴也都能直接用。需要套件的情境通常是:
- 動畫要跟著 React 狀態中斷、反轉或接續,例如拖曳放開後回彈
- 元件卸載時要先播完離場動畫
- 版面位置改變時要自動補間(layout animation)
- 多段動畫要排成時間軸,或與捲動進度綁定
三個套件的基本資料
| Motion | GSAP | React Spring | |
|---|---|---|---|
| npm 套件 | motion(React 從 motion/react 匯入) | gsap 與 @gsap/react | @react-spring/web |
| 授權 | MIT | Standard "No Charge" License | MIT |
| API 風格 | 宣告式:在元件 props 寫目標狀態 | 命令式:在 hook 裡呼叫 gsap.to()、建立 timeline | Hook:useSpring 回傳動畫值,套在 animated.* 元素 |
| 時間模型 | 時長與 easing,或 spring | 時長與 easing,timeline 排程 | 彈簧物理(質量、張力、摩擦) |
| React 版本 | peer 依賴 React 18、19 | @gsap/react 要求 React 17 以上 | peer 依賴 React 16.8 到 19 |
Motion
"use client";
import type { ReactNode } from "react";
import { motion } from "motion/react";
export function FadeIn({ children }: { children: ReactNode }) {
return (
<motion.div
initial={{ opacity: 0, y: 16 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.4, ease: "easeOut" }}
>
{children}
</motion.div>
);
}Motion 的強項是和 React 的資料流貼合:離場動畫用 AnimatePresence,版面補間只要加 layout prop。依官方文件,它會優先用瀏覽器原生的 Web Animations API 執行,遇到 spring 或手勢這類原生 API 做不到的情況才改用 JavaScript。
大小方面,官方的減量指南列出:完整的 motion 元件約 34kb;改用 m 元件搭配 LazyMotion 初次渲染約 4.6kb;只用 useAnimate 的精簡版約 2.3kb。
減少動態效果:在根部包一層 <MotionConfig reducedMotion="user">,使用者開啟系統設定時,所有 motion 元件的 transform 與 layout 動畫會自動關閉,透明度等其他屬性照常(文件)。
Motion 另有付費的 Motion+(範例、進階元件等),核心套件本身維持 MIT。
GSAP
"use client";
import { useRef, type ReactNode } from "react";
import gsap from "gsap";
import { useGSAP } from "@gsap/react";
gsap.registerPlugin(useGSAP);
export function FadeIn({ children }: { children: ReactNode }) {
const ref = useRef<HTMLDivElement>(null);
useGSAP(
() => {
gsap.from(ref.current, { opacity: 0, y: 16, duration: 0.4, ease: "power2.out" });
},
{ scope: ref },
);
return <div ref={ref}>{children}</div>;
}GSAP 適合時間軸複雜的動畫,例如多個元素依序進場、與捲動綁定的分段敘事(ScrollTrigger)。useGSAP 會把建立的動畫包在 gsap.context() 裡,元件卸載時自動清除,React 18 以後 Strict Mode 重複執行 effect 也不會留下殘影(React 整合文件)。在點擊事件裡建立的動畫要用 hook 回傳的 contextSafe() 包起來才會被清除。減少動態效果可用 gsap.matchMedia() 搭配 (prefers-reduced-motion: no-preference) 條件。
授權變更: GSAP 被 Webflow 收購後,自 2025 年 4 月 30 日起改用 Standard "No Charge" License。依 gsap.com/licensing,商業專案可免費使用,原本付費會員才能用的 SplitText、MorphSVG 等外掛也一併免費。條款中的禁止用途是:未經書面同意,不得用 GSAP 打造與 Webflow 動畫編輯器競爭的無程式碼視覺動畫工具。一般網站與應用程式不受影響。這份授權不是 MIT 這類開源授權,npm 上的 license 欄位也直接指向這份條款,公司有授權審查流程時要另外送審。
React Spring
"use client";
import type { ReactNode } from "react";
import { animated, useSpring } from "@react-spring/web";
export function FadeIn({ children }: { children: ReactNode }) {
const styles = useSpring({
from: { opacity: 0, y: 16 },
to: { opacity: 1, y: 0 },
});
return <animated.div style={styles}>{children}</animated.div>;
}React Spring 以彈簧物理描述動畫,沒有固定時長,被中途打斷時會從當下的速度自然接續,適合拖曳、手勢與需要「手感」的互動。它屬於 pmndrs 生態系,@react-spring/three 可以直接驅動 react-three-fiber 的 3D 場景。npm 上的最新版是 10.1.2(2026 年 6 月發布)。減少動態效果有內建的 useReducedMotion,搭配 Globals.assign({ skipAnimation }) 讓所有 spring 直接跳到終點。
Next.js App Router 與 Server Components
動畫一定在瀏覽器執行,三個套件的 hook 都不能在 Server Component 裡呼叫。實務做法:
- 把用到動畫的元件獨立成檔案,最上方加
"use client",Server Component 再引用它。上面三段範例都是這種寫法。 - Motion 另外提供
motion/react-client入口,可以取代"use client"加motion/react的寫法,官方說明這樣能減少送到客戶端的 JavaScript(安裝文件)。 useGSAP在伺服器端會退回useEffect,不會報錯,但檔案仍然要標記"use client"。- 有初始狀態的進場動畫(例如
opacity: 0)會在 SSR 輸出裡就是隱藏狀態,JavaScript 載入失敗時內容會看不見。重要內容可以考慮只做位移、不從完全透明開始。
怎麼選
- 以 React 元件為中心的 UI 動畫(進場、離場、layout、手勢):Motion。和 JSX 的寫法最一致。
- 時間軸複雜、捲動敘事、SVG 變形、逐字拆分:GSAP。外掛齊全,現在也免費。先確認授權條款是否符合公司的審查要求。
- 物理感強的互動、3D 場景:React Spring。
- 只是 hover 與簡單進場:CSS 與 Tailwind 就夠,不必加套件。
同一個專案混用兩個套件並不少見,例如 UI 用 Motion、行銷頁的長捲動敘事用 GSAP。要注意的是兩者同時控制同一個元素的 transform 會互相覆蓋。
動畫元件庫放在哪裡
上面三個是「動畫引擎」,你仍然要自己設計每個效果的時間、曲線與減少動態效果的退化方式。動畫元件庫則是建立在這些引擎上、已經寫好的元件,例如跑馬燈、邊框光束、文字逐字進場。
近年常見的發佈方式是 registry 模式:用 CLI 把元件原始碼複製進專案的 components/ui/,node_modules 裡不會多出一個元件庫套件。好處是可以直接改程式碼,沒有元件庫自己的執行期依賴;代價是更新要重新安裝或手動合併。真正的執行期依賴是元件底下用的動畫引擎。
WebberUI 屬於這一類。元件以 motion/react 為基礎,安裝時 CLI 會一併加入 motion 依賴;有動態的元件都會依 prefers-reduced-motion 停用或簡化動畫。如果你已經選了 Motion,這些元件的寫法與你自己的程式碼一致,改起來不需要切換思路。
npx webberui@latest add https://webberui.com/r/split-text.json把這個效果裝進你的專案
在專案資料夾執行指令,CLI 會加入原始碼與依賴套件,再依下方使用範例引用元件。
npx webberui@latest add split-text從 快速開始 開始,或到 元件總覽 依分類瀏覽。要比較各家動畫元件庫,可以看 動畫 React 元件庫比較;想看具體的 CSS 寫法,可以讀 Tailwind 無限跑馬燈 與 動態漸層邊框的三種做法。