CSSのtransitionが効かない時の原因&対処法
2021/04/26
2021/05/17
CSSのtransition
プロパティは、マウスオーバー時のアニメーションを指定できるプロパティです。
WEBデザインにちょっとしたアクセントを加えたい時に便利なCSSですが、何らかの原因で上手く機能しないことがあります。
しかし、その原因のほとんどは、コーディング上のほんの小さなミスだったりします。
今回は、transition
が効かない時の原因とその対処法についてまとめてみました。
もくじ
transitionの基本的な使い方
まずtransitonの基本的な使い方を簡単におさらいしておきましょう。
transitionはマウスオーバー時の色や大きさ、位置などの変化に「時間」を設けるためのプロパティです。
マウスオーバー時の変化にはCSS疑似クラス:hover
を使いますが、transition
が指定されていない場合、変化前後の切り替わりが一瞬です。
transition
を追加することによって「じわじわ色が移り変わる」「最初は早く、最後は緩やかに」等のアニメーション的な動作が加えることができます。
CSSでは、以下のように記述します。
transition: 1s background linear 2s;
値は左から順番に「開始から終了までの時間」「適用するプロパティ」「変化の仕方」「開始するまでの時間」が指定されています。
つまり上記のコードは「1秒(1s
)かけて背景(background
)が一定に変化(linear
)するアニメーションを2秒後(2s
)に開始する」という意味です。
ちなみに「適用するプロパティ」には、個別指名しても良いですが「all
」を指定することで一括できます。
例えば、以下のように:hover
に複数プロパティが存在し、全て同じ時間をかけて変化を実行したい場合には「all
」で一括してしまったほうが楽です。
1 2 3 4 5 6 7 8 9 10 11 |
div.box { width: 200px; height: 200px; border: 1px solid #333; transition: 1s all linear; /* background・colorともに適用 */ } div.box:hover { background: #db7093; color: #fff; } |
また、transitionの値として不要なものがあれば省略可能です。
上記のコードでは、最後の値(開始するまでの時間)を省略していますが、アニメーションは機能します。
transitionが効かない時の原因&対処法
では、transition
の基本的な使い方を踏まえたうえで「効かない」原因を探っていきましょう。
今回はtransition
や:hover
周辺のコーデイングで「ありがち」なミスを考えてみました。
基本的な項目もありますが、一つ一つチェックしていってみてください。
1.:hoverにtransitionを指定している
最も多いミスの一つがtransition
プロパティを疑似クラス内に指定してしまっていることです。
例えば、以下のような感じにです。
1 2 3 4 5 6 7 8 9 10 11 |
div.box { width: 200px; height: 200px; border: 1px solid #333; } div.box:hover { background: #db7093; color: #fff; transition: 1s all linear; } |
カーソルを離した時に元のスタイルに戻るアニメーションが発動しない場合など、このようなミスをしている可能性が高いです。
transitionの正しい指定位置は:hover内ではなく、本要素に直接です。
1 2 3 4 5 6 7 8 9 10 11 |
div.box { width: 200px; height: 200px; border: 1px solid #333; transition: 1s all linear; } div.box:hover { background: #db7093; color: #fff; } |
これで往路・復路ともにtransition
が効くようになります。
2.インライン要素にtransformを指定している
マウスオーバー時の変化させる時に、よく使われるスタイルがtransform
プロパティです。
位置の移動や回転など、バラエティに富んだ変化を加えることができます。
しかし、transform
は一部のインライン要素(a
やspan
など)には効きません。
そのため、以下のように:hover
内でtransform
を指定しても、transition
どころかマウスオーバーイベント自体が発生しないのです。
1 |
<p><a href="#">インライン要素</a>にtransformは適用できる?</p> |
1 2 3 4 5 6 7 8 |
a { text-decoration: none; transition: 1s all; } a:hover { transform: translateY(3px); /* <a>はインライン要素なのでtransformは機能しない */ } |
とは言え、インライン要素が効かないだけなので、他の表示形式に変えてしまえば問題は解決します。
1 2 3 4 5 6 7 8 9 |
a { display: inline-block; text-decoration: none; transition: 1s all; } a:hover { transform: translateY(3px); } |
上記のように、インライン要素のスタイルにdisplay:inline-block
の一文を加えてください。
3.positionが正しく設定されていない
transition
で要素の位置を移動させたい時、position
プロパティを使うことがあります。
とても使い勝手の良いCSSですが、設定項目が多くケアレスミスしやすいです。
position
の基本的な使い方については詳しい説明を省きますが、「transition
との組み合わせ」の中で見落としがちなミスとして、主に以下の2点をチェックしてみてください。
- 親要素にも
position
が設定されているか - 子要素に「変化前の位置」が指定されているか
一つずつ見ていきましょう。
まず、position
は基本的に親要素と子要素の両方に設定が必要です。
例えば、以下のような入れ子構造のボックスがあると仮定し、子要素(child_box)の位置をマウスオーバーで移動させたい場合。
1 2 3 |
<div class="parent_box"> <div class="child_box"></div> </div> |
この時、親要素(parent_box)のposition
がデフォルト値のstatic
以外に指定されていないと、子要素の位置をposition
で変更することができません。
必ず親要素のスタイルでposition
をrelative
などに指定しておきましょう。
1 2 3 4 5 6 |
.parent_box { width: 200px; height: 50px; border: 1px solid #333; position: relative; } |
次に見落としがちなのが、transition
との組み合わせでは変化前の位置を指定しておく必要がある、ということです。
例えば、以下のようなコードではtransition
の設定は効きません。
1 2 3 4 5 6 7 8 9 10 11 |
.child_box { width: 100px; height: 50px; background: #db7093; position: absolute; transition: 1.5s all ease-in-out; /* 無効 */ } .parent_box:hover .child_box { left: 100px; } |
下図のようにマウスオーバーイベント自体は実行されているものの、transition
のスタイルは無視されているのがわかります。
position
のマウスオーバーイベントにtransition
を適用させるためには、子要素にデフォルトの位置を指定します。
1 2 3 4 5 6 7 8 9 10 11 12 |
.child_box { width: 100px; height: 50px; background: #db7093; position: absolute; left: 0; transition: 1.5s all ease-in-out; } .parent_box:hover .child_box { left: 100px; } |
マウスオーバーイベントでleft
を指定している場合は、left
の開始地点を子要素に記しておきましょう。
4.transitionにdisplayを指定している
マウスオーバーによる表示・非表示を切り替えたい時display
を使うことがあります。
display: none
を指定することで要素をまるごと非表示にしてから、:hover
時のスタイルをdisplay: block
に戻して表示させるテクニックです。
例えば、下図のようなドロップダウン式のメニューを作る際、:hover
でdisiplay
の値を操作することによって、下層メニューの表示・非表示を切り替えています。
この「触れると表示されるメニュー」に、今度はtransitionを指定して時間をかけて表示させてみたいと思います。
まず、HTMLは以下の通りです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<ul class="parent_list"> <li> <a href="#" class="heading">Fishes</a> <ul class="child_list"> <li><a href="#">Mackerel</a></li> <li><a href="#">Sardine</a></li> <li><a href="#">Salmon</a></li> </ul> </li> <li> <a href="#" class="heading">Meats</a> <ul class="child_list"> <li><a href="#">Beef</a></li> <li><a href="#">Pork</a></li> <li><a href="#">Chicken</a></li> </ul> </li> <li> <a href="#" class="heading">Vegetables</a> <ul class="child_list"> <li><a href="#">Carrot</a></li> <li><a href="#">Cabbage</a></li> <li><a href="#">Green pepper</a></li> </ul> </li> </ul> |
このようにリストを入れ子状態にし、下層メニュー(.child_list)の初期値にdisplay: none
を、マウスオーバー時のスタイル(:hover
)にdisplay: block
を指定しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
ul { list-style-type: none; padding: 0; } .parent_list { position: relative; } .parent_list > li { display: inline-block; } .parent_list a{ display: block; width: 200px; padding: 5px 20px; background: #fff; border-right: 1px solid #333; border-left: 1px solid #333; border-bottom: 1px solid #333; } .heading{ border-top: 1px solid #333; } .child_list { position: absolute; display: none; /* 下層メニューを非表示 */ transition: 1s all linear; } .parent_list li:hover .child_list { display: block; /* 下層メニューを表示 */ } .child_list a:hover{ background: #aaa; } |
しかし、残念ながら上記を反映させてもtransition
は効きません(※マウスオーバーイベントはきちんと機能します)。
というのも、どうやらtransition
でdisplay
を操作することはできないようなのです。
そこで代替策としてopacity
プロパティを使います。
先ほどのCSSコードの28~36行目を次のように変更してください。
1 2 3 4 5 6 7 8 9 10 11 |
.child_list { position: absolute; visibility: hidden; opacity: 0; transition: 1s all linear; } .parent_list li:hover .child_list { visibility: visible; opacity: 1; } |
opacity
は不透明度を調整するプロパティですが、「0」を指定すると全く見えない状態(=非表示)に、「1」を指定すると完全に見えている状態(=表示)にすることが可能です。
transition
を指定することで、下層メニューがジワジワと現れ出るような動きになります。
ちなみに、visibility
もhidden
(非表示)からvisible
(表示)に切り替えるよう指定してください。
というのも、opacity
だけだと透明な範囲に触れるとマウスイベントが発生してしまうためです。
下図のように親メニューに触れた時のみ下層メニューが表示させるようにするには、opacity
&visibility
とセットでtransition
を設定してください。
(※画質の劣化により枠線の表示が乱れていますが、実際の使用では枠線がきちんと表示されます)
まとめ
今回は、transitionが効かない時の原因と対処法を解説しました。
マウスオーバー時の変化にアニメーションのような動きを与えることができるtransition
は、今ではWEBデザインには欠かせない存在です。
しかし一方で、ルールなどが多く初心者がつまづきやすいプロパティでもあります。
もしもtransition
が上手く機能しない時は、再びこの記事を参照してみてください。
最後にtransition
が効かない時に確認すべきポイントを簡単におさらいしておきましょう。
:hover{}
内ではなく、変化させたい要素のスタイルにtransition
を指定しようspam
やa
などのインライン要素をtranform
(変形)させることはできないposition
で要素を移動させる時は、カーソルが触れる前の位置を指定しようdiplay
はtransition
で操作できない ⇒opacity
&visiblity
で対応しよう