Webサイトを制作する時、CSSのtransitionが期待通りに動かないと感じることはありませんか。hoverで色が変わるはずが一瞬で切り替わる、または高さがアニメーションするはずが何も起こらない。そんな悩みを抱える方に向けて、transitionが効かない原因を段階的に整理し、原因別に具体的なチェックポイントと解決策をご紹介します。基本的な理解から最新のテクニックまで網羅し、CSS transitionで動かないを解消する内容です。
目次
transition 効かない 原因として考えられる基本的なポイント
まずはtransitionが効かない際の“基礎的な原因”を把握することが重要です。プロパティの種類、初期値・終了値の設定の仕方、durationの設定など、よくある間違いを整理します。これらが満たされていないとどれだけコードを整えてもtransitionは動きません。
アニメーションできないプロパティを使っている
CSSでtransition可能なプロパティと、transition不可能なプロパティがあります。たとえばdisplayは“none”⇔“block”などの状態の変化ですが、これらは中間状態が定義できないためアニメーションできません。autoから数値系の値へのtransitionもブラウザによって非対応だったり不安定だったりするため注意が必要です。
初期値が明示されていない、autoを使っている
対象のプロパティにおける変化前の値(初期値)が未指定、または“auto”になっているケースでは、中間値をブラウザが計算できないためtransitionが飛びます。widthやheightの初期値を明確なpxや%で指定することが基本です。autoから数値への遷移などは避けてmax-heightなどの工夫を使うのも有効です。
transition-duration が 0s または指定ミス
durationがデフォルトで0秒だと、値の変化は瞬間的になりアニメーションが走りません。またdurationの単位ミス、秒(s)とミリ秒(ms)を間違えるケースも頻出です。さらにtransitionプロパティ全体の構文が誤っていたり、複数プロパティを指定する際にdurationやプロパティ名の数が一致していないことでも問題が起こります。
動かないケースで見落としがちな実践上の原因
基本ポイントを抑えた上で、実際の開発で遭遇しやすい“実用的な原因”を探ります。JavaScriptとの組み合わせ、CSSの競合、ステート変更のタイミングなど。これらに気づかずにデバッグが難航するケースがあります。
display:none からの復帰状態での適用不足
要素が display:none の状態から block 等に変わると、display プロパティ自体はアニメーション対象外なので、visibility + opacity の組み合わせや max-height を使ってアコーディオン状に展開するといった方法で代替する必要があります。display:none の直後に style を変更しても transition は発火しません。
JavaScriptでの状態変更が同一フレーム内で行われている
JavaScriptで初期スタイルと変化後のスタイルをほぼ同時に設定するとブラウザがまとめて処理し、変化前の表示がスキップされてtransitionが動きません。setTimeout や requestAnimationFrame を使って初期状態を描画させてから変化をトリガーすることで解決できます。
CSSの優先順位や specificity の競合、上書き
別のスタイルシートやフレームワーク、ライブラリのCSSがより詳細度の高いセレクタや !important 指定などで transition を無効化または上書きしていることがあります。DevTools の computed style を確認し、transition や変化対象プロパティが意図した値であるかをチェックすることが有効です。
プロパティ別の特殊なケースと回避策
プロパティによっては transition を使う際に“特別な準備や工夫”が必要になるものがあります。transform や position 系、autoの値からの変更など。これらのプロパティごとにどのような問題が起きやすく、どう処理すれば動くようになるか説明します。
position系(top, left, bottom, right)の transition が効かない
これらのプロパティは要素の position が static(初期値)だと無効です。relative や absolute などに設定し、初期値を 0px など明示しておく必要があります。また終了値が auto だと中間値の計算ができず transition は発火しません。transform を使う方法が負荷や動作の安定性の点で好ましいケースもあります。
transform や translate の値が state によって変化しない設定
transform を使う場合、transition の対象プロパティに transform を指定し、初期状態と変更後の状態を両方明示します。hover や class の付け替えで変化させることが一般的です。変化が起きていない(例えば初期と終了が同じ値だったり)場合は動かないのでプロパティ値を確認することが大切です。
ユーザ設定(prefers-reduced-motion)やアクセシビリティ設定による制限
利用者の環境で「動き制限モード」が有効になっていると、transition や animation を制限する設定がブラウザにより尊重されます。その場合は transition の動作がそもそも抑制されてしまうため、アニメーションが見えないことがあります。アクセシビリティの観点でも確認しておくべき事項です。
最新の環境でよくあるバグや注意点
最新ブラウザでも transition が“効かない”と感じる状況があります。これらは環境依存や仕様の解釈、パフォーマンス最適化の影響などによるものです。開発者が迷いやすいポイントを最新情報としてまとめます。
auto を使用している場合のブラウザ間の差異
auto の扱いはブラウザごとに実装が異なることがあります。あるブラウザでは auto から固定値への transition が部分的に動作して見えるものの、他では全く無視されるなどの差が見られます。そのため auto を transition の対象値に含めるのはなるべく避け、max-height や max-width、transform scale や translate などを代替策として用いるのが安定です。
開発ツールやビルド環境によるCSS圧縮・ポストプロセッサの影響
開発時と本番環境で CSS が圧縮されたりポストプロセスされる際に、transition プロパティが消されたり順序が入れ替わったりすることがあります。またベンダープレフィックスが消えて互換性に影響する場合や、class 名が書き換えられる設計が影響することもあります。ビルド結果を確認して transition 周りが意図通り残っているかを確認する必要があります。
遅延 (transition-delay) が想定と異なる動作をすることがある
delay を使うことで変化を遅らせることができますが、delay の指定がない場合でもデフォルト delay が 0s となります。delay を明示するとともに、transition の開始タイミングを state 変更イベント(hover, focus, class)から正しく起こしているか確認することが重要です。また delay を指定していても要素がそもそも hidden な状態だと delay の後の見え方も影響を受けます。
transition 効かない 原因 を診断するためのチェックリストとテンプレート
実践的に「transition 効かない 原因」を特定するには、以下のようなチェックリストを使って順に確認することが効果的です。自分のコードをこのテンプレートに沿って見直すことで多くの原因を網羅できます。
ステップ1:CSSプロパティと値の見直し
まず transition の対象となるプロパティがアニメーション可能か確認します。display や position の一部などは非対応です。次に初期値と変化後の値が auto でないこと、また数値指定が明確であることを確認します。
ステップ2:transition プロパティの設定確認
transition-property, transition-duration, transition-timing-function, transition-delay が正しく設定されているか、ショートハンドを使う場合は省略しすぎていないかチェックします。duration が 0s でないかも必須確認項目です。
ステップ3:ステートの変化が確実に起きているか
:hover, focus, class の付け替え、JavaScript イベントを用いて変化させているかを確認します。同一フレーム内で初期・変化後が設定されていないか、変化が可視状態に反映される状態か、hidden/display:none 状態からの状態変化でないかなどを順に確認します。
ステップ4:ブラウザの設定・環境を確認
ユーザの環境でアクセシビリティ設定が入っていないか、prefers-reduced-motion が有効かどうかを確認します。また開発ツールで computed style を見て transition やプロパティの状態が期待通りか、本番ビルド後に CSS が圧縮や加工で変わっていないかを確認します。
実例とコードで見る原因と修正パターン
理論だけでは理解しづらいケースもあります。ここではよくある具体例を取り上げ、どのような原因で transition が効いていなかったか、どう修正すれば動くようになるかを具体的なコードと共に解説します。
例1:display を使ったフェードインが動かない
要素が initially display:none に設定されており、hover などで display:block にすることでフェードインさせようとしても、display プロパティは transition の対象外なのでフェード効果は出ません。代替として visibility を hidden から visible、opacity を 0 から 1 にする方法が一般的です。display は即時切り替えとなるためタイミングのズレがありません。
例2:height:auto から height:0 に collapse させようとして失敗する
height: auto から固定の数値へ transition しようとすると、ブラウザは初期値 auto を数値に変換できないため、アニメーションが飛びます。これを避けるためには max-height を使い、始まりの値を十分大きな px 値に設定しておき collapse 先を 0 に設定する方法がよく使われます。あるいは JS で要素の scrollHeight を取得し explicit height を設定する方式もあります。
例3:JS で class を付けるタイミングが早すぎるパターン
JavaScriptで初期状態と変化後の状態をほぼ同時に与えると、ブラウザ側で state の変化が見えず transition が発火しません。このような場合は requestAnimationFrame を使って次のフレームで変化を適用する方法や、setTimeout を使って微小な遅延を設ける方法が解決策です。
例4:CSS 書き間違いや複数指定の不整合
transition 宣言で複数プロパティを指定する時、プロパティ名の数と duration や timing-function の数が一致していないと意図しない動きになることがあります。またセレクタの指定ミス・タイポ・ショートハンド記法の誤用もよくある原因です。ショートハンド使うなら syntax をよく確認してください。
まとめ
CSS の transition が効かない原因は多岐にわたりますが、原理を理解し、順序立ててチェックすることで多くは短時間で解決できます。まずは対象プロパティがアニメーション可能か、初期値と終了値が明示されているかどうかを確認すること。
次に、transition プロパティ自身が正しく設定されているか、duration が 0 ではないか、state 変更のトリガーが適切かどうかを見ます。display:none からの復帰や auto 値の遷移、そして JS や build 環境による上書きや環境設定も忘れず。
最後に、具体例を通じて自分のコードと照らし合わせ、どのパターンに当てはまるかを洗い出すことが大切です。これらのチェックポイントを順に確認すれば、CSS transition が動かない原因を突き止め、スムーズなアニメーション実装が可能になります。
コメント