見せる・隠す(Show / Hide)

フェード・スライド・トグルアニメーションをFramer MotionとCSS Transitionで実装・比較

🔗 このページはFramer Motion / CSS Transitionを使ったReact実装です。バニラJSでの実装は要素の表示・非表示ページを参照してください。
Framer Motion

読み込み中...

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

export default function ShowHideFramerDemo() {
  const [visible, setVisible] = useState(true);

  return (
    <>
      <button onClick={() => setVisible(v => !v)}>トグル</button>

      {/* フェード */}
      <AnimatePresence>
        {visible && (
          <motion.div
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            exit={{ opacity: 0 }}
            transition={{ duration: 0.4 }}
          >
            フェードするコンテンツ
          </motion.div>
        )}
      </AnimatePresence>

      {/* スライドダウン */}
      <AnimatePresence>
        {visible && (
          <motion.div
            initial={{ opacity: 0, height: 0 }}
            animate={{ opacity: 1, height: 'auto' }}
            exit={{ opacity: 0, height: 0 }}
            transition={{ duration: 0.4, ease: 'easeInOut' }}
            style={{ overflow: 'hidden' }}
          >
            スライドするコンテンツ
          </motion.div>
        )}
      </AnimatePresence>

      {/* mode="wait" で切り替えアニメーション */}
      <AnimatePresence mode="wait">
        {visible ? (
          <motion.div
            key="shown"
            initial={{ opacity: 0, scale: 0.8 }}
            animate={{ opacity: 1, scale: 1 }}
            exit={{ opacity: 0, scale: 0.8 }}
            transition={{ duration: 0.3 }}
          >
            表示中
          </motion.div>
        ) : (
          <motion.div
            key="hidden"
            initial={{ opacity: 0, scale: 0.8 }}
            animate={{ opacity: 1, scale: 1 }}
            exit={{ opacity: 0, scale: 0.8 }}
            transition={{ duration: 0.3 }}
          >
            非表示
          </motion.div>
        )}
      </AnimatePresence>
    </>
  );
}

jQueryで書くとこうなる

jQueryでは .fadeIn().slideDown() などのメソッドで手軽にアニメーションを実装できました。Reactでは Framer Motion の AnimatePresencemotion コンポーネントを使うことで、同等以上の表現が可能です。
js
// show / hide
$('#box').hide();
$('#box').show();

// toggle
$('#box').toggle();

// fadeIn / fadeOut
$('#box').fadeIn(400);
$('#box').fadeOut(400);

// fadeToggle
$('#box').fadeToggle(400);

// slideDown / slideUp
$('#box').slideDown(400);
$('#box').slideUp(400);

// slideToggle
$('#box').slideToggle(400);
💡 上記のデモは、React / Next.jsです。Next.jsの基本セットアップは 公式ドキュメントを参照してください。

実装方法の比較

項目Framer MotionCSS Transition
DOMから削除AnimatePresenceでアンマウント時もアニメーション可能DOMに残りopacityで隠す(アクセシビリティ注意)
高さアニメーションheight: 'auto' をアニメーション可能max-heightで代替(厳密な高さ指定が必要)
切り替えアニメーションmode='wait'で前のアニメーション完了後に次を開始同時遷移のみ(前後のアニメーション制御が困難)
設定コスト高:framer-motionのインストールが必要低:追加ライブラリ不要
パフォーマンスGPUアクセラレーション・60fps最適化済みtransform/opacityはGPUアクセラレーション対象

AnimatePresence のポイント

  • AnimatePresence で囲むことで、コンポーネントのアンマウント時にも exit アニメーションが実行される
  • mode="wait" を指定すると、前のコンポーネントのexitアニメーション完了後に次のenterが始まる
  • height: 0 → 'auto' のアニメーションはFramer Motionでのみ可能(CSSではmax-heightで代替)
  • • CSS Transitionでは要素がDOMに残るため、スクリーンリーダーに読み上げられる可能性がある

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

Next.js + Framer Motion で「見せる・隠す」アニメーションを実装してください。
- ボタンクリックで要素をフェードイン・フェードアウト
- ボタンクリックで要素をスライドダウン・スライドアップ
- AnimatePresence を使ってアンマウント時もアニメーションさせる
- TypeScript / Tailwind CSS v4 を使用

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