DEMO
カードをクリックすると幅の変化に合わせて全体が再配置されます
CODE
<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>
.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); }
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不要の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
クリックした要素のサイズ変化に合わせて兄弟要素がなめらかに再配置されるレイアウトアニメーションを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
※当サイトはAmazonアソシエイトプログラムの参加者です。リンクから商品をご購入いただくと、当方に紹介料が発生します。
学びを止めない · AMAZONサブスク
※当サイトはAmazonアソシエイトプログラムの参加者です。リンクから商品をご購入いただくと、当方に紹介料が発生します。
状態変化によって要素のサイズや位置が変わったとき、その前後の差分を自動的に補間してなめらかなアニメーションにするFramer Motionの看板機能。motion要素に layout プロパティを1つ付けるだけで、内部的にはFLIP(First-Last-Invert-Play)テクニックが適用されます。
手書きのFLIP実装では要素の位置計測・transform反転・アニメーション再生を自分で管理する必要がありますが、layoutプロパティはそれを全て肩代わりします。タブの選択インジケータ、カードの展開・折りたたみ、リストの並び替えなど「レイアウトが動く」UI全般で使えます。