切り替え演出(Transition)

フェード・スライド・スケールなどのコンテンツ切り替えアニメーションをFramer MotionとCSS Transitionで実装・比較

🔗 このページはFramer Motion / CSS Transitionを使ったReact実装です。バニラJSでの実装はCSSアニメーションの制御ページを参照してください。
Framer Motion

読み込み中...

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

const ITEMS = ['春 🌸', '夏 🌿', '秋 🍂', '冬 ❄️'];

export default function TransitionDemo() {
  const [current, setCurrent] = useState(0);

  return (
    <>
      {/* フェード切り替え */}
      <AnimatePresence mode="wait">
        <motion.div
          key={current}
          initial={{ opacity: 0 }}
          animate={{ opacity: 1 }}
          exit={{ opacity: 0 }}
          transition={{ duration: 0.3 }}
        >
          {ITEMS[current]}
        </motion.div>
      </AnimatePresence>

      {/* スライド切り替え(右から) */}
      <AnimatePresence mode="wait">
        <motion.div
          key={current}
          initial={{ opacity: 0, x: 60 }}
          animate={{ opacity: 1, x: 0 }}
          exit={{ opacity: 0, x: -60 }}
          transition={{ duration: 0.3, ease: 'easeInOut' }}
        >
          {ITEMS[current]}
        </motion.div>
      </AnimatePresence>

      {/* スケール切り替え */}
      <AnimatePresence mode="wait">
        <motion.div
          key={current}
          initial={{ opacity: 0, scale: 0.85 }}
          animate={{ opacity: 1, scale: 1 }}
          exit={{ opacity: 0, scale: 0.85 }}
          transition={{ duration: 0.3 }}
        >
          {ITEMS[current]}
        </motion.div>
      </AnimatePresence>

      <div>
        {ITEMS.map((_, i) => (
          <button key={i} onClick={() => setCurrent(i)}>{i}</button>
        ))}
      </div>
    </>
  );
}

jQueryで書くとこうなる

jQueryでは .fadeOut() のコールバック内で次のコンテンツを .fadeIn() する方法が一般的でした。Reactでは Framer Motion の AnimatePresencemode="wait" を使うことで、退場アニメーション完了後に次のコンテンツを表示する処理を宣言的に書けます。
js
// フェードで切り替え
$('#content-old').fadeOut(300, function () {
  $('#content-new').fadeIn(300);
});

// スライドで切り替え
$('#content-old').slideUp(300, function () {
  $('#content-new').slideDown(300);
});

// hide/show で即時切り替え(アニメーションなし)
$('#content-old').hide();
$('#content-new').show();

// animate() でカスタム切り替え
$('#content-old').animate({ opacity: 0 }, 300, function () {
  $(this).hide();
  $('#content-new').css({ opacity: 0 }).show().animate({ opacity: 1 }, 300);
});
💡 上記のデモは、React / Next.jsです。Next.jsの基本セットアップは 公式ドキュメントを参照してください。

実装方法の比較

項目Framer MotionCSS Transition
退場アニメーションAnimatePresence + exitで自動制御DOMに残したままopacityで隠す
切り替えタイミングmode="wait"で退場完了後に入場同時遷移のみ(前後の制御が困難)
keyによる制御keyが変わると自動でexit→enterが走る手動でクラス付け外しが必要
設定コスト高:framer-motionのインストールが必要低:追加ライブラリ不要
実装のシンプルさ宣言的で直感的クラス管理が煩雑になりやすい

AnimatePresence mode="wait" のポイント

  • AnimatePresence で囲むことで、コンポーネントのアンマウント時にも exit アニメーションが実行される
  • mode="wait" を指定すると、前の要素の exit アニメーション完了後に次の要素の initial → animate が始まる
  • key が変わると同じコンポーネントでも別要素として扱われ、exit → enter が自動で走る
  • • CSS Transitionでは退場完了のタイミングを検知しにくく、setTimeout でアニメーション時間と同じ待機が必要になる

🤖 AIプロンプトテンプレート

Next.js + Framer Motion でコンテンツの切り替え演出を実装してください。
- ボタンクリックでコンテンツをフェード・スライド・スケールで切り替え
- AnimatePresence の mode="wait" を使って退場アニメーション完了後に入場させる
- key を使ってコンテンツの切り替えを検知する
- TypeScript / Tailwind CSS v4 を使用

⚠️ このプロンプトはあくまでたたき台です。AIの回答はモデルやバージョン、会話の文脈によって毎回異なります。意図通りに動かない場合は、条件を追記・修正してお使いください。