No.104
CARD CSSJSFRAMER

Framer Layout Animation

クリックした要素の幅が変わると、兄弟要素もなめらかに再配置されるレイアウトアニメーション。Framer Motionのlayoutプロパティ1つで実現する看板機能。

DEMO

カードをクリックすると幅の変化に合わせて全体が再配置されます

CODE

HTML
<div class="demo-stage fla-stage">
  <p class="fla-hint">カードをクリックすると幅の変化に合わせて全体が再配置されます</p>
  <div class="fla-row">
    <button class="fla-card fla-active" type="button"><span>01</span>LAYOUT</button>
    <button class="fla-card" type="button"><span>02</span>MOTION</button>
    <button class="fla-card" type="button"><span>03</span>FLIP</button>
  </div>
</div>
CSS
.fla-stage { display:flex; flex-direction:column; align-items:center; justify-content:center; gap:1.2rem; padding:3rem 1.5rem; background:#0F0F12; min-height:280px; }
.fla-hint { color:rgba(255,255,255,.4); font-family:'Oswald',sans-serif; letter-spacing:.12em; font-size:.75rem; margin:0; text-align:center; }
.fla-row { display:flex; gap:.9rem; width:min(460px,100%); }
.fla-card {
  flex:1 1 0; min-width:0; padding:1.6rem .5rem; border-radius:14px; cursor:pointer;
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:.4rem;
  background:#1A1A1A; border:1px solid rgba(255,255,255,.08);
  color:#fff; font-family:'Oswald',sans-serif; font-size:.8rem; letter-spacing:.14em;
  transition: flex-grow .6s cubic-bezier(.22,1,.36,1), background .3s ease, border-color .3s ease;
}
.fla-card span { color:#E91B89; font-size:1.3rem; }
.fla-card.fla-active { flex-grow:2.4; background:#232328; border-color:rgba(233,27,137,.55); }
JS
document.querySelectorAll('.fla-card').forEach(function(card){
  card.addEventListener('click', function(){
    document.querySelectorAll('.fla-card').forEach(function(c){ c.classList.remove('fla-active'); });
    card.classList.add('fla-active');
  });
});
FRAMER MOTION (React)

ライブデモはFramer Motion不要のCSS等価版(flex-growをtransition)。下がReact + Framer Motionの実装です。layoutプロパティを付けるだけで、状態変化によるサイズ・位置の変化が自動でアニメーションします。

import { useState } from "react"
import { motion } from "framer-motion"

const cards = ["01", "02", "03"]

export default function LayoutCards() {
  const [active, setActive] = useState(0)
  return (
    <div className="flex gap-4">
      {cards.map((t, i) => (
        <motion.div
          key={t}
          layout
          onClick={() => setActive(i)}
          transition={{ layout: { duration: 0.55, ease: [0.22, 1, 0.36, 1] } }}
          style={{ flexGrow: active === i ? 2.4 : 1 }}
          className="card"
        >
          {t}
        </motion.div>
      ))}
    </div>
  )
}

AI PROMPT

Claude Code Cursor v0
PROMPT
クリックした要素のサイズ変化に合わせて兄弟要素がなめらかに再配置されるレイアウトアニメーションをFramer Motionで作って。各カードの <motion.div> に layout プロパティを付け、選択状態に応じて style={{ flexGrow: active ? 2.4 : 1 }} を切り替えるだけで、位置とサイズの変化が自動的にFLIPアニメーションになる。transition={{ layout: { duration: 0.55, ease: [0.22,1,0.36,1] } }} で速度を調整。CSSで近似するなら flex-grow に transition を付ける。タブ・アコーディオン・ギャラリーの選択UIに。

Acceptance criteria: works with prefers-reduced-motion (animation disabled), zero console errors, zero layout shift

AIエージェントでの実装ガイド → Claude Code でWebアニメーションを実装する

BOOKS · PR · AMAZON

📖 なかしまぁ先生のCSSアニメーション入門 📖 UIデザインの教科書 新版 マルチデバイス時代のインターフェース設計 📖 Fundamentals of Web Animation with GSAP

※当サイトはAmazonアソシエイトプログラムの参加者です。リンクから商品をご購入いただくと、当方に紹介料が発生します。

学びを止めない · AMAZONサブスク

📚 Kindle Unlimited — 技術書・デザイン書が読み放題。30日無料体験 → 🎧 Audible — 移動中に耳で学ぶオーディオブック。30日無料体験 → 📦 Amazon Prime — Prime Reading・配送特典つき。30日無料体験 → 🎵 Music Unlimited — 作業用BGMに。1億曲が聴き放題・30日無料体験 →

※当サイトはAmazonアソシエイトプログラムの参加者です。リンクから商品をご購入いただくと、当方に紹介料が発生します。

RELATED EFFECTS

↗ MORE
→ FRAMER ANIMATEPRESENCE → FRAMER SPRING HOVER → FLIP CARD

Framer Motion Layout Animation とは

状態変化によって要素のサイズや位置が変わったとき、その前後の差分を自動的に補間してなめらかなアニメーションにするFramer Motionの看板機能。motion要素に layout プロパティを1つ付けるだけで、内部的にはFLIP(First-Last-Invert-Play)テクニックが適用されます。

手書きのFLIP実装では要素の位置計測・transform反転・アニメーション再生を自分で管理する必要がありますが、layoutプロパティはそれを全て肩代わりします。タブの選択インジケータ、カードの展開・折りたたみ、リストの並び替えなど「レイアウトが動く」UI全般で使えます。