Framer Motion入門 - Reactアニメーションを実装する

中級 | 45分 で読める | 2025.12.07

公式ドキュメント

今回やること

Framer Motionは、Reactで宣言的にアニメーションを実装できるライブラリです。

アニメーションは装飾ではなく、状態変化を理解しやすくするために使うと効果的です。

この記事では次を学びます。

  • 基本的なアニメーション
  • バリアント
  • ジェスチャー
  • レイアウトアニメーション
  • AnimatePresence

実践メモ: framer-motionはReact専用です。インストール後すぐにmotion.divなどの要素が使えます。

Step 1: セットアップ

# framer-motion 11+
npm install framer-motion

Step 2: 基本的なアニメーション

import { motion } from 'framer-motion';

function BasicAnimation() {
 return (
 <motion.div
 initial={{ opacity: 0, y: 20 }}
 animate={{ opacity: 1, y: 0 }}
 transition={{ duration: 0.5 }}
 >
 Hello Animation!
 </motion.div>
 );
}

Step 3: ホバーとタップ

function InteractiveBox() {
 return (
 <motion.button
 whileHover={{ scale: 1.1 }}
 whileTap={{ scale: 0.95 }}
 className="px-4 py-2 bg-blue-500 text-white rounded"
 >
 Click me
 </motion.button>
 );
}

ポイント: initial→animate→transitionの3つのpropsがアニメーションの基本パターンです。

Step 4: バリアント

const containerVariants = {
 hidden: { opacity: 0 },
 visible: {
 opacity: 1,
 transition: {
 staggerChildren: 0.1,
 },
 },
};

const itemVariants = {
 hidden: { opacity: 0, y: 20 },
 visible: { opacity: 1, y: 0 },
};

function StaggeredList() {
 const items = ['Item 1', 'Item 2', 'Item 3'];

 return (
 <motion.ul
 variants={containerVariants}
 initial="hidden"
 animate="visible"
 >
 {items.map((item, i) => (
 <motion.li key={i} variants={itemVariants}>
 {item}
 </motion.li>
 ))}
 </motion.ul>
 );
}

実践メモ: staggerChildrenを使うと子要素が順番にアニメーションし、リストの表示が格段にリッチになります。

Step 5: AnimatePresence

import { motion, AnimatePresence } from 'framer-motion';
import { useState } from 'react';

function ToggleContent() {
 const [isVisible, setIsVisible] = useState(true);

 return (
 <div>
 <button onClick={() => setIsVisible(!isVisible)}>Toggle</button>

 <AnimatePresence>
 {isVisible && (
 <motion.div
 initial={{ opacity: 0, height: 0 }}
 animate={{ opacity: 1, height: 'auto' }}
 exit={{ opacity: 0, height: 0 }}
 >
 Content here
 </motion.div>
 )}
 </AnimatePresence>
 </div>
 );
}

注意: AnimatePresence内の子要素には必ず一意のkeyを付けてください。keyがないとexit animationが動作しません。

Step 6: レイアウトアニメーション

function LayoutAnimation() {
 const [selected, setSelected] = useState<number | null>(null);

 return (
 <div className="grid grid-cols-3 gap-4">
 {[1, 2, 3].map((item) => (
 <motion.div
 key={item}
 layout
 onClick={() => setSelected(selected === item ? null : item)}
 className={`p-4 bg-blue-500 rounded cursor-pointer ${
 selected === item ? 'col-span-3' : ''
 }`}
 >
 {item}
 </motion.div>
 ))}
 </div>
 );
}

ポイント: layoutpropを付けるだけでCSS変更時に自動的にスムーズなアニメーションが適用されます。

Step 7: スクロールアニメーション

import { motion, useScroll, useTransform } from 'framer-motion';

function ScrollAnimation() {
 const { scrollYProgress } = useScroll();
 const opacity = useTransform(scrollYProgress, [0, 0.5], [1, 0]);
 const scale = useTransform(scrollYProgress, [0, 0.5], [1, 0.8]);

 return (
 <motion.div style={{ opacity, scale }}>
 Scroll to see animation
 </motion.div>
 );
}

Step 8: ドラッグ

function DraggableBox() {
 return (
 <motion.div
 drag
 dragConstraints={{ left: 0, right: 300, top: 0, bottom: 300 }}
 dragElastic={0.2}
 whileDrag={{ scale: 1.1 }}
 className="w-20 h-20 bg-blue-500 rounded cursor-grab"
 />
 );
}

アニメーションを入れる目的

Framer Motionは簡単にリッチな動きを作れますが、動きが多いほど良いUIになるわけではありません。ユーザーの視線誘導、状態変化の理解、画面遷移の自然さを助けるために使うと効果的です。

特に一覧、モーダル、タブ、エラーメッセージなどは、表示と非表示の変化を少し滑らかにするだけで分かりやすくなります。一方で、常に動き続ける装飾や大きすぎる移動は、操作の邪魔になることがあります。

品質チェック

  • 動きが情報理解を助けているか
  • prefers-reduced-motionに配慮しているか
  • 初回表示でレイアウトが跳ねないか
  • スマホで重くならないか

動作確認

アニメーションを入れたら、次を確認します。

確認項目OKの状態
表示/非表示開閉時に意図した動きになる
keyAnimatePresence の子に一意のkeyがある
reduced motion動きを減らす設定に配慮している
レイアウト初回表示でガタつかない
スマホスクロールやタップを邪魔しない

動きが多すぎる場合は、時間を短くするより、動かす要素と目的を減らす方が改善しやすいです。

練習

次のUIにアニメーションを追加してください。

  1. ボタン押下でカードを表示する
  2. 表示時は opacity と y を変える
  3. 非表示時は AnimatePresence でexitを動かす
  4. 一覧の並び替えに layout を付ける
  5. reduced motion時は大きな移動を避ける

次のステップ

UIコンポーネントと組み合わせる場合は shadcn/ui入門 が役立ちます。状態管理が必要な場合は Zustand入門、React Hooksの基礎は React Hooks完全マスター を確認してください。

まとめ

Framer Motionは宣言的なAPIで複雑なアニメーションを簡単に実装できます。バリアントとAnimatePresenceで美しいUIを作りましょう。

参考リソース

← 一覧に戻る
PR
PR
PR
PR