アコーディオンを作りたい。transition: height .3s;
を書いたのに、開閉が一瞬でパカッと切り替わる――
「CSS が効かない!?」と嘆く諸君、それは height:auto に潜む“仕様の壁”だ。
Contents
🧩 症状再現:高さ 0 → auto がパキッと切替
隠れていたテキストが表示されるはず…
<style>
.panel {
overflow: hidden;
height: 0;
transition: height .3s ease;
}
.panel.open {
height: auto;
}
</style>
<div>
<button id="btn">Toggle</button>
<div class="panel" id="panel">
<p>隠れていたテキストが表示されるはず…</p>
</div>
</div>
<script>
btn.onclick = () => panel.classList.toggle('open');
</script>
開け閉めしてみると一切アニメーションせず、一瞬で全開・全閉。
なぜ transition
が無視されるのか!?

🔍 真犯人:auto
は数値に補間できない
CSS Transition は 数値 を0%→100%で補間して描画する仕組み。
しかし height:auto
は計算後に決まる“実測値”であり、
ブラウザは 0px → 何px? を事前に把握できない。結果、補間不能 → 一括描画になる。
🛠️ 解決策:3 つの王道アプローチ
- max-height ハック
実際に入り得る最大値を指定し、0 → 500px など数値遷移に置き換える。.panel { max-height: 0; transition: max-height .3s ease; } .panel.open { max-height: 500px; /* 十分大きい値 */ }
- CSS animation + JS で動的数値
開くときにscrollHeight
を取得 & inline-style で高さを入れる → 閉じたら 0。
例:panel.style.height = panel.scrollHeight + 'px'
- height ではなく transform
スケールY や clip-path を使い、GPU フレンドリ&auto 問題回避。.panel { transform: scaleY(0); transform-origin: top; transition: transform .3s ease; } .panel.open { transform: scaleY(1); }
📝 実装例:CSS だけで滑らかアコーディオン
ここに表示したいコンテンツが入ります。
<style>
.panel {
overflow: hidden;
max-height: 0; /* 閉じた状態 */
transition: max-height .3s ease;
}
.panel.open {
max-height: 500px; /* 十分余裕を持たせる */
}
</style>
<button id="btn">Toggle</button>
<div class="panel" id="panel">
<p>ここに表示したいコンテンツが入ります。</p>
</div>
<script>
const btn = document.getElementById('btn');
const panel = document.getElementById('panel');
btn.onclick = () => panel.classList.toggle('open');
</script>
最大高さ 500px を超える可能性がある場合は JS で scrollHeight
を代入する方法に切り替えましょう。
📖 早見チェックリスト
- transition するプロパティは「数値補間可能」か?
- 0 → auto で詰まったら
max-height
or transform スケールを検討 - JS 併用の場合は
scrollHeight
/offsetHeight
を活用
🔧 ベストプラクティス:UI に応じた戦略を選ぶ
手法 | メリット | デメリット |
---|---|---|
max-height ハック | CSS だけで完結 | 最大値を超えると欠ける |
JS + height | 正確な高さで開閉 | JS 依存&コード量増 |
transform スケール | GPU 高速・滑らか | 内部要素のアンチエイリアス揺れ |
🧠 まとめ
height:auto
は補間不可 → transition は効かない。- max-height / JS / transform で“数値遷移”に変換。
- UI仕様・パフォーマンス要件で手法を選択せよ。
🔥 団長のエール
「効かない」と怒る前に、ルールを知ろう!
CSS が嫌がるのは曖昧な指示。
数値で示せばブラウザも全力で応えてくれる。
設計の精度こそ、フロントエンドの武器だ。
戦え、そして滑らかに動け! お前の UI のように!!🔥