
Framer Motion 完全ガイド - React向け高性能アニメーションライブラリ
Framer Motionとは
Framer Motionは、React向けのプロダクションレディなアニメーションライブラリです。シンプルなAPIで複雑なアニメーションを実現でき、パフォーマンスも優れています。
もともとはデザインツール「Framer」の内部で使用されていたアニメーションエンジンをオープンソース化したもので、実績のある信頼性の高いライブラリです。CSSアニメーションやJavaScriptのrequestAnimationFrameを直接扱う必要がなく、Reactの考え方(宣言的UI)に沿った形でアニメーションを記述できるのが最大の特徴です。
他のアニメーションライブラリとの比較
| ライブラリ | 特徴 | 向いている用途 |
|---|---|---|
| Framer Motion | 宣言的API、React専用、豊富な機能 | React SPA、複雑なUI |
| GSAP | 高性能、細かい制御、学習コスト高め | ゲーム、広告、高度なアニメーション |
| Anime.js | 軽量、シンプル、フレームワーク非依存 | シンプルなアニメーション |
| React Spring | 物理ベース、Framer Motionに似ている | 自然な動きが必要な場面 |
特徴
- 宣言的なAPI:
animate、initial、exitなどのpropsでアニメーションを定義。命令的なコードを書く必要がない - ジェスチャー対応:
whileHover、whileTap、whileDragで直感的なインタラクションを簡単に実装 - バリアント: 複数のアニメーション状態を定義し、親子間で自動的に伝播。複雑な連動アニメーションも簡潔に書ける
- レイアウトアニメーション: CSSの変更を自動検出してスムーズにアニメーション。手動でのサイズ計算が不要
- AnimatePresence: DOM要素の削除時にexitアニメーションを実行。React標準では難しい「消える」演出が簡単
- Springアニメーション: 物理ベースの自然な動き。イージング関数を考える必要がなく、直感的なパラメータで調整可能
インストール
Framer Motionは単一パッケージで提供されており、追加の依存関係は不要です。
npm install framer-motion注意点:
- React 18以上が必要です
- Next.js App Routerで使用する場合、アニメーションを使うコンポーネントには
'use client'ディレクティブが必要です - SSRと互換性があり、サーバーサイドでも安全に動作します
基本的な使い方
Framer Motionの基本は非常にシンプルです。通常のHTML要素を motion. プレフィックス付きのコンポーネントに置き換えるだけで、アニメーション機能が有効になります。
motion.divコンポーネント
motion.div、motion.span、motion.buttonなど、すべての標準HTMLタグに対応するmotionコンポーネントが用意されています。これらは通常のHTMLタグと同じように使用でき、追加のpropsでアニメーションを定義します。
import { motion } from 'framer-motion';
function App() {
return (
<motion.div
initial={{ opacity: 0, scale: 0.5 }}
animate={{ opacity: 1, scale: 1 }}
transition={{ duration: 0.5 }}
>
Hello Framer Motion!
</motion.div>
);
}主要なprops
| Props | 説明 | 例 |
|---|---|---|
| initial | アニメーション開始時(マウント時)の状態 | {{ opacity: 0, y: 20 }} |
| animate | アニメーション終了時(目標)の状態 | {{ opacity: 1, y: 0 }} |
| transition | アニメーションの設定(時間、イージング、タイプなど) | {{ duration: 0.5, ease: 'easeOut' }} |
| exit | アンマウント時の状態(AnimatePresenceと併用) | {{ opacity: 0, scale: 0.8 }} |
Framer Motionは initial と animate の差分を自動的に計算し、スムーズな補間を行います。transition を省略した場合は、デフォルトでSpringアニメーションが適用されます。
基本的なアニメーション
初期表示アニメーション
無限回転
クリックでアニメーション
<motion.div
initial={{ opacity: 0, scale: 0.5 }}
animate={{ opacity: 1, scale: 1 }}
transition={{ duration: 0.8 }}
/>上のデモでは、ページ読み込み時にフェードイン・スケールアップする要素、無限回転する要素、クリックでアニメーションが再生される要素を確認できます。
ホバー・タップアニメーション
ユーザーインタラクションに対する視覚的フィードバックは、UIの品質を大きく左右します。Framer Motionでは、whileHoverとwhileTapを使用して、CSSの:hover疑似クラスでは実現しにくい滑らかなアニメーションを簡単に実装できます。
特にボタンやカードなどのインタラクティブ要素に適用すると、クリック可能であることを直感的に伝え、操作した際の満足感を高めることができます。
<motion.button
whileHover={{ scale: 1.1 }}
whileTap={{ scale: 0.95 }}
transition={{ type: 'spring', stiffness: 400, damping: 17 }}
>
クリック!
</motion.button>ホバー・タップアニメーション
ホバー: 拡大 + 回転
ホバー: グラデーション変化
Springアニメーション
<motion.button
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
transition={{ type: "spring", stiffness: 400 }}
/>上のデモでは、ホバー時の拡大・回転、グラデーション変化、そしてSpringアニメーションを使ったボタンの押し込み効果を確認できます。
使用可能なジェスチャーprops
| Props | 説明 | 使用例 |
|---|---|---|
whileHover | ホバー中のアニメーション | ボタン、カード、リンクのフィードバック |
whileTap | クリック/タップ中のアニメーション | ボタンの押し込み効果 |
whileFocus | フォーカス中のアニメーション | フォーム入力フィールドのハイライト |
whileDrag | ドラッグ中のアニメーション | ドラッグ可能要素の視覚的強調 |
whileInView | ビューポート内に入った時のアニメーション | スクロールで表示されるコンテンツ |
ポイント: whileHoverとwhileTapを組み合わせることで、ホバー時に拡大、タップ時に縮小という自然な押しボタンの動きを表現できます。
トランジション設定
transitionプロパティは、アニメーションの**「どのように動くか」**を制御します。Framer Motionでは、主に2種類のアニメーションタイプが用意されています。
Springアニメーション
Springアニメーションは、Framer Motionのデフォルトのアニメーションタイプです。物理ベースのバネシミュレーションにより、自然で心地よい動きを実現します。
従来のイージング関数(ease-in-outなど)とは異なり、終了時間を指定するのではなく、バネの物理特性を指定します。これにより、速度に応じた自然な減速や、跳ね返りの動きを表現できます。
<motion.div
animate={{ x: 100 }}
transition={{
type: 'spring',
stiffness: 500, // バネの硬さ(高いほど速く動く)
damping: 15, // 減衰(低いほど跳ねる)
mass: 1 // 質量(高いほど重く動く)
}}
/>Springパラメータの詳細
| パラメータ | 説明 | 低い値 | 高い値 |
|---|---|---|---|
| stiffness | バネの硬さ | ゆっくり、柔らかい動き | 速い、キビキビした動き |
| damping | 減衰(抵抗) | 跳ね返りが多い | すぐに止まる |
| mass | 質量 | 軽い、素早く動く | 重い、ゆっくり動く |
| velocity | 初速度 | - | アニメーション開始時の速度を指定 |
スプリングアニメーション設定
Bouncy
stiffness: 500
damping: 15
Smooth
stiffness: 100
damping: 20
Stiff
stiffness: 700
damping: 30
Gentle
stiffness: 50
damping: 10
※ 各ボールをクリックするとスプリングの違いを確認できます
stiffness: バネの硬さ(高いほど速く動く)
damping: 減衰(低いほど跳ねる)
mass: 質量(高いほど重く動く)
transition={{
type: "spring",
stiffness: 500, // バネの硬さ
damping: 15, // 減衰
mass: 1 // 質量
}}上のデモで各ボールをクリックすると、stiffnessとdampingの組み合わせによる動きの違いを確認できます。
Tweenアニメーション
従来のキーフレームベースのアニメーションです。正確な時間制御が必要な場合や、無限ループするアニメーションに適しています。
<motion.div
animate={{ rotate: 360 }}
transition={{
type: 'tween',
duration: 2,
ease: 'easeInOut',
repeat: Infinity
}}
/>主なイージング関数
| イージング | 説明 | 使用例 |
|---|---|---|
linear | 一定速度 | ローディングスピナー、進行バー |
easeIn | ゆっくり開始 | 退場アニメーション |
easeOut | ゆっくり終了 | 登場アニメーション |
easeInOut | ゆっくり開始・終了 | 往復アニメーション |
circIn/Out | 円形カーブ | より顕著な加減速 |
backIn/Out | 少し戻る動き | 強調したい動き |
anticipate | 予備動作付き | 投げる、ジャンプなどの動き |
Spring vs Tween の使い分け:
- Spring: ユーザー操作への反応、自然な動きが欲しい時
- Tween: 正確な時間制御、無限ループ、シーケンシャルなアニメーション
バリアント(Variants)
バリアントは、アニメーション状態に名前を付けて再利用可能にする仕組みです。複数の要素で同じアニメーションパターンを使いたい場合や、親子間でアニメーションを連動させたい場合に非常に便利です。
バリアントのメリット
- コードの再利用: 同じアニメーション定義を複数の要素で共有
- 親子連動: 親要素のアニメーション状態が自動的に子要素に伝播
- オーケストレーション:
staggerChildrenやdelayChildrenで子要素のタイミングを制御 - 可読性向上: アニメーションロジックをコンポーネントから分離
const containerVariants = {
hidden: { opacity: 0 },
visible: {
opacity: 1,
transition: {
staggerChildren: 0.1, // 子要素を0.1秒ずつずらして表示
delayChildren: 0.2 // 子要素のアニメーション開始を遅延
}
}
};
const itemVariants = {
hidden: { opacity: 0, y: 20 },
visible: { opacity: 1, y: 0 }
};
function List() {
return (
<motion.ul
variants={containerVariants}
initial="hidden"
animate="visible"
>
{items.map(item => (
<motion.li key={item} variants={itemVariants}>
{item}
</motion.li>
))}
</motion.ul>
);
}バリアント & スタッガーアニメーション
const containerVariants = {
hidden: { opacity: 0 },
visible: {
opacity: 1,
transition: { staggerChildren: 0.1 }
}
};
<motion.div variants={containerVariants} initial="hidden" animate="visible">
{items.map(item => <motion.div variants={itemVariants} />)}
</motion.div>上のデモでは、ボタンをクリックすると複数のアイコンが順番にアニメーションします。これがstaggerChildrenの効果です。
staggerChildrenの効果
staggerChildrenを使用すると、子要素のアニメーションを順番に少しずつずらして実行できます。リストやグリッドの表示に最適で、「ドミノ倒し」のような連鎖的なアニメーションを簡単に実現できます。
オーケストレーションオプション
| オプション | 説明 | 例 |
|---|---|---|
staggerChildren | 子要素間のアニメーション開始の遅延 | 0.1(0.1秒ずつずらす) |
delayChildren | 子要素全体のアニメーション開始遅延 | 0.3(親から0.3秒後に開始) |
staggerDirection | スタッガーの方向 | 1(順方向), -1(逆方向) |
when | 親子のアニメーション順序 | "beforeChildren", "afterChildren" |
AnimatePresence - 出入りアニメーション
Reactの標準的な条件付きレンダリングでは、要素がアンマウントされると即座にDOMから削除されます。これは、「消える」アニメーションを実装する上で大きな障壁となります。
AnimatePresenceコンポーネントを使用すると、要素がDOMから削除される前にexitアニメーションを実行できます。これにより、モーダルのフェードアウト、リスト項目の削除アニメーション、ページトランジションなど、多くのUI演出が可能になります。
なぜAnimatePresenceが必要なのか
// これだけでは「消える」アニメーションは実行されない
{isVisible && <motion.div animate={{ opacity: 1 }} />}
// isVisibleがfalseになると即座に消えるAnimatePresenceで囲むことで、exitアニメーションが完了するまでDOM要素が保持されます。
import { motion, AnimatePresence } from 'framer-motion';
function Modal({ isOpen }) {
return (
<AnimatePresence>
{isOpen && (
<motion.div
initial={{ opacity: 0, scale: 0.8 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.8 }}
transition={{ type: 'spring' }}
>
モーダルコンテンツ
</motion.div>
)}
</AnimatePresence>
);
}AnimatePresence - 出入りアニメーション
※ 要素をクリックすると削除されます
<AnimatePresence mode="popLayout">
{items.map(item => (
<motion.div
key={item}
initial={{ opacity: 0, scale: 0 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0 }}
/>
))}
</AnimatePresence>上のデモでは、「+ 追加」ボタンで要素を追加し、各要素をクリックすると削除されます。削除時にスケールダウンしながらフェードアウトするのがexitアニメーションの効果です。
AnimatePresenceのmode
| mode | 説明 | 使用例 |
|---|---|---|
sync(デフォルト) | 新旧要素が同時にアニメーション | 一般的なリスト操作 |
wait | 古い要素のexitが完了してから新しい要素がenter | ページトランジション、ステップウィザード |
popLayout | 削除される要素がレイアウトから「ポップ」され、他の要素がスムーズに移動 | リスト項目の削除 |
重要なポイント
- keyプロパティ:
AnimatePresenceの直下の要素には必ず一意のkeyを設定してください。Reactがどの要素が追加/削除されたかを判断するために必要です。 - initial=: 初回マウント時のアニメーションを無効にしたい場合に使用します(アコーディオンなど)。
スクロール連動アニメーション
スクロール連動アニメーションは、ユーザーのスクロール操作に応じて要素が変化する演出です。パララックス効果、プログレスバー、スクロールで現れるコンテンツなど、モダンなWebサイトでよく見られる表現を実現できます。
Framer MotionのuseScrollとuseTransformフックを使用すると、スクロール位置を監視し、その値を別の値(opacity、scale、positionなど)に変換してアニメーションに適用できます。
useScrollとuseTransformの関係
useScroll: スクロール位置を0〜1の値(progress)として取得useTransform: progressを別の値(opacity, x, scaleなど)にマッピングstyleに適用: マッピングされた値をmotion要素のstyleに渡す
import { motion, useScroll, useTransform } from 'framer-motion';
import { useRef } from 'react';
function ScrollAnimation() {
const ref = useRef(null);
const { scrollYProgress } = useScroll({
target: ref,
offset: ['start end', 'end start']
});
// scrollYProgress: 0 → 0.5 → 1 を
// opacity: 0 → 1 → 0 にマッピング
const opacity = useTransform(scrollYProgress, [0, 0.5, 1], [0, 1, 0]);
const scale = useTransform(scrollYProgress, [0, 0.5, 1], [0.8, 1, 0.8]);
return (
<motion.div ref={ref} style={{ opacity, scale }}>
スクロールで変化
</motion.div>
);
}上のデモでは、ページをスクロールすると3つの要素がそれぞれ異なる方法でアニメーションします。スクロール進捗バーもuseScrollで実装されています。
useScrollのオプション
const { scrollYProgress } = useScroll({
target: ref, // 監視する要素
offset: ['start end', 'end start'], // トリガー位置
container: containerRef // スクロールコンテナ(省略時はウィンドウ)
});offsetの指定方法
offsetは['要素の位置 ビューポートの位置', '要素の位置 ビューポートの位置']の形式で指定します。
| 指定 | 意味 |
|---|---|
'start end' | 要素の上端がビューポートの下端に達した時(要素が見え始める) |
'center center' | 要素の中央がビューポートの中央に達した時 |
'end start' | 要素の下端がビューポートの上端に達した時(要素が見えなくなる) |
パフォーマンスのポイント: useScrollとuseTransformはReactの再レンダリングを発生させずにアニメーションを更新するため、非常に高いパフォーマンスを実現しています。
ドラッグ機能
Framer Motionは、ドラッグ&ドロップ機能を驚くほど簡単に実装できます。dragpropを追加するだけで、要素をマウスやタッチでドラッグ可能にできます。
ドラッグ機能は、カルーセル、スライダー、並べ替え可能なリスト、スワイプで削除するUI、インタラクティブなチュートリアルなど、様々な場面で活用できます。
基本的な使い方
<motion.div
drag // ドラッグを有効化
dragConstraints={{ left: 0, right: 300, top: 0, bottom: 200 }} // 移動範囲
dragElastic={0.1} // 範囲外でのバウンド量
dragMomentum={true} // 慣性
whileDrag={{ scale: 1.1 }} // ドラッグ中のスタイル
/>ドラッグ機能
自由ドラッグ
範囲制限付き
X軸のみ
<motion.div
drag
dragConstraints={constraintsRef}
dragElastic={0.1}
whileDrag={{ scale: 1.1 }}
/>上のデモでは、自由にドラッグできる要素、範囲制限付きの要素、X軸のみに移動できる要素を試すことができます。
ドラッグ関連のprops
| Props | 説明 | 例 |
|---|---|---|
drag | true、"x"、"y"でドラッグ方向を制限 | drag="x" |
dragConstraints | ドラッグの範囲(ref or オブジェクト) | {{ left: -100, right: 100 }} |
dragElastic | 範囲外でのバウンド量(0-1) | 0.2(20%のバウンド) |
dragMomentum | 慣性の有効/無効 | false(慣性無効) |
dragTransition | ドラッグ後のアニメーション設定 | {{ bounceStiffness: 600 }} |
dragSnapToOrigin | ドラッグ終了時に元の位置に戻る | true |
親要素を範囲として使用する
dragConstraintsにref(参照)を渡すと、その要素の範囲内でのみドラッグ可能になります。
function DraggableInContainer() {
const constraintsRef = useRef(null);
return (
<div ref={constraintsRef} style={{ width: 300, height: 200 }}>
<motion.div
drag
dragConstraints={constraintsRef}
/>
</div>
);
}ポイント: dragElasticを0に設定すると、範囲外に出ようとしても完全に制限されます。1に近づけると、範囲外に引っ張ってから跳ね返る「ゴムバンド」のような動きになります。
レイアウトアニメーション
レイアウトアニメーションは、Framer Motionの最も強力な機能の一つです。通常、CSSでサイズや位置の変化をアニメーションさせるには、変更前後の値を計算し、適切なtransitionを設定する必要があります。
layoutpropを使用すると、Framer Motionが自動的に変更を検出し、スムーズにアニメーションします。開発者は何も計算する必要がありません。
layoutプロパティの仕組み
- Reactが再レンダリングを実行
- Framer Motionが要素の新しい位置・サイズを計算
- 変更前の状態から変更後の状態へ自動的にアニメーション
<motion.div layout>
{isExpanded ? <ExpandedContent /> : <CollapsedContent />}
</motion.div>これだけで、コンテンツの切り替え時にサイズがスムーズにアニメーションします。
layoutIdによる共有要素トランジション
layoutIdは、異なる場所にある要素同士を「同じもの」として認識させる機能です。リストからモーダルへの展開、タブ切り替え時のインジケーター移動など、「要素が移動する」演出を簡単に実現できます。
これは、ネイティブアプリでよく見られる「Shared Element Transition」をWebで実現するものです。
// カードリスト
{items.map(item => (
<motion.div
layoutId={`card-${item.id}`}
onClick={() => setSelected(item.id)}
>
{item.title}
</motion.div>
))}
// モーダル
<AnimatePresence>
{selected && (
<motion.div layoutId={`card-${selected}`}>
<ExpandedCard />
</motion.div>
)}
</AnimatePresence>レイアウトアニメーション
カードをクリックすると展開します(layoutId)
自動レイアウトアニメーション(layout prop)
<motion.div layoutId="shared-element" />
<motion.div layout /> // 自動レイアウトアニメーション上のデモでは、2つの機能を確認できます:
- layoutId: カードをクリックすると、リスト内のカードがモーダルに「変形」するように見える
- layout: 下部の要素をクリックすると、サイズ変更がスムーズにアニメーション
layoutの種類
| 値 | 説明 | 使用例 |
|---|---|---|
true | 位置とサイズ両方をアニメーション | 一般的なレイアウト変更 |
"position" | 位置のみをアニメーション | 並べ替え可能なリスト |
"size" | サイズのみをアニメーション | アコーディオン、展開パネル |
実践的なパターン
ここでは、実際のプロジェクトでよく使われるアニメーションパターンを紹介します。これらのコードスニペットは、そのままコピーして使用したり、カスタマイズのベースとして活用できます。
ページトランジション
ページ間の移動時にアニメーションを追加すると、アプリケーション全体の一体感が向上します。Next.jsのPages Routerを使用している場合、_app.tsxでAnimatePresenceを使用します。
// _app.tsx (Next.js Pages Router)
import { AnimatePresence, motion } from 'framer-motion';
function MyApp({ Component, pageProps, router }) {
return (
<AnimatePresence mode="wait">
<motion.div
key={router.route}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -20 }}
transition={{ duration: 0.3 }}
>
<Component {...pageProps} />
</motion.div>
</AnimatePresence>
);
}スクロールで表示されるセクション
ランディングページやブログ記事で、スクロールに応じてコンテンツがフェードインする演出です。whileInViewとviewportを組み合わせます。
function Section({ children }) {
return (
<motion.section
initial={{ opacity: 0, y: 50 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, margin: '-100px' }}
transition={{ duration: 0.6 }}
>
{children}
</motion.section>
);
}ポイント:
viewport.once: true: 一度表示されたら再度アニメーションしない(パフォーマンス向上)viewport.margin: トリガー位置を調整('-100px'で画面に入る100px前にアニメーション開始)
ローディングスピナー
無限回転するローディングスピナーです。repeat: Infinityで永続的にアニメーションします。
const spinnerVariants = {
animate: {
rotate: 360,
transition: {
duration: 1,
repeat: Infinity,
ease: 'linear'
}
}
};
function Spinner() {
return (
<motion.div
variants={spinnerVariants}
animate="animate"
style={{
width: 40,
height: 40,
border: '3px solid #e0e0e0',
borderTop: '3px solid #667eea',
borderRadius: '50%'
}}
/>
);
}アコーディオン
FAQやサイドメニューでよく使われるアコーディオンです。height: 'auto'へのアニメーションはCSSでは難しいですが、Framer Motionなら簡単に実現できます。
function Accordion({ title, children, isOpen, onToggle }) {
return (
<div>
<button onClick={onToggle}>{title}</button>
<AnimatePresence initial={false}>
{isOpen && (
<motion.div
initial={{ height: 0, opacity: 0 }}
animate={{ height: 'auto', opacity: 1 }}
exit={{ height: 0, opacity: 0 }}
transition={{ duration: 0.3 }}
style={{ overflow: 'hidden' }}
>
{children}
</motion.div>
)}
</AnimatePresence>
</div>
);
}ポイント:
initial={false}:AnimatePresenceに渡すと、初回マウント時のアニメーションをスキップoverflow: 'hidden': 高さが変化する際にコンテンツがはみ出さないようにする
パフォーマンス最適化
Framer Motionは高度に最適化されていますが、使い方によってはパフォーマンスに影響を与えることがあります。以下のベストプラクティスを守ることで、60fpsのスムーズなアニメーションを維持できます。
1. transform系のプロパティを優先
x、y、scale、rotate、opacityはGPUアクセラレーションが効くため高速です。これらはブラウザの「コンポジットレイヤー」で処理され、メインスレッドをブロックしません。
一方、width、height、top、leftなどは**レイアウト再計算(リフロー)**が発生するため、特に多数の要素がある場合に処理が重くなります。
// ✅ Good: transform系(GPU処理)
<motion.div animate={{ x: 100, scale: 1.2 }} />
// ❌ Avoid: レイアウト系(リフロー発生)
<motion.div animate={{ width: 200, left: 100 }} />2. layoutプロパティの最適化
layoutプロパティは便利ですが、必要以上に使用するとパフォーマンスに影響します。位置またはサイズの一方だけが変化する場合は、適切な値を指定しましょう。
// position/sizeのどちらかだけ必要な場合
<motion.div layout="position" /> // 位置のみ
<motion.div layout="size" /> // サイズのみ3. 不要な再レンダリングを避ける
Reactのstate更新は再レンダリングを引き起こしますが、useMotionValueを使用するとReactの再レンダリングなしでアニメーション値を更新できます。これは、ドラッグやスクロールなど、頻繁に値が変化する場面で特に有効です。
// useMotionValueを使用して再レンダリングを回避
import { motion, useMotionValue, useTransform } from 'framer-motion';
function OptimizedComponent() {
const x = useMotionValue(0);
const opacity = useTransform(x, [-100, 0, 100], [0, 1, 0]);
// xが変化してもReactの再レンダリングは発生しない
return <motion.div style={{ x, opacity }} drag="x" />;
}その他のヒント
- 大量の要素: リストに100以上の要素がある場合、すべてにアニメーションを適用するのは避ける
- will-change: Framer Motionは自動的に
will-changeを設定するため、手動で追加する必要はない - reduce-motion:
prefers-reduced-motionメディアクエリを尊重し、アクセシビリティに配慮する
まとめ
Framer Motionは、Reactアプリケーションにアニメーションを追加するための最も強力で使いやすいライブラリの一つです。宣言的なAPIにより、複雑なアニメーションも直感的に実装でき、パフォーマンスも最適化されています。
Framer Motionの強み
| 強み | 詳細 |
|---|---|
| 学習コストが低い | 宣言的なAPIで直感的。CSSアニメーションの知識がなくても始められる |
| 機能が豊富 | ジェスチャー、レイアウト、SVGアニメーション、スクロール連動など幅広い機能 |
| パフォーマンス | GPUアクセラレーション、useMotionValueによる再レンダリング回避 |
| TypeScriptサポート | 完全な型定義により、IDEの補完とエラーチェックが利用可能 |
| エコシステム | 豊富なドキュメント、活発なコミュニティ、継続的なアップデート |
使い分けの目安
| ユースケース | 推奨機能 | 難易度 |
|---|---|---|
| 初期表示アニメーション | initial / animate | ⭐ |
| ホバー・クリック | whileHover / whileTap | ⭐ |
| リスト表示 | variants + staggerChildren | ⭐⭐ |
| モーダル・ページ遷移 | AnimatePresence + exit | ⭐⭐ |
| スクロール連動 | useScroll / whileInView | ⭐⭐ |
| ドラッグ操作 | drag + dragConstraints | ⭐⭐ |
| レイアウト変化 | layout / layoutId | ⭐⭐⭐ |
次のステップ
- 基本をマスター:
animate、initial、transitionを使った簡単なアニメーションから始める - ジェスチャーを追加:
whileHover、whileTapでインタラクティブ性を向上 - バリアントを活用: 複数の要素を連動させるアニメーションを実装
- 高度な機能に挑戦:
AnimatePresence、useScroll、layoutで本格的なアニメーションを構築
Framer Motionを使いこなして、ユーザー体験を向上させるアニメーションを実装しましょう!