CSSアニメーションでフェードイン・フェードアウトを実現するためにはopacity
を使うのが一般的ですが、「要素の領域が残っちゃうからdisplay:none;
でやりたい…」と思ったことがある方もいらっしゃるかと思います。
基本的に、display
ってtransition
が効かないのでアニメーションさせることができないんですよね。
が、できるようになったんです!本記事ではCSSの書き方を紹介してまいります。

これを夢見ていたコーダーさんは少なくないのではないでしょうか… (感涙)
@starting-styleとは?
@starting-style
とは、アニメーションさせる要素にプロパティの開始値を定義するためのCSSのアットルールです。
通常、display: none;
が指定されている要素にはトランジションが効きません。
そこで@starting-style
ルールを使い、トランジション開始時の初期スタイルを定義することによって、diplay: none;
が指定されていたとしても正しくトランジションを発火することができます。
これはdiplay: none;
からアニメーションさせる要素には必須となります。
記法は二パターンありますが、ネストを使用したほうが簡潔に記述できるので、下記の『記法①(入れ子式)』を推奨します。
/* ================================
記法①(入れ子式)
================================ */
.example:hover {
/* トランジション後 */
@starting-style {
/* トランジション前 */
}
}
/* ================================
記法②(既存のアットルール式)
================================ */
@starting-style {
.example:hover {
/* トランジション前 */
}
}
.example:hover {
/* トランジション後 */
}
opacityとdisplayのアニメーションコード比較
JSを使わないメガドロップダウンメニューで比較してみましょう。
【従来の書き方】opacity
見えなくするだけのopacity
に加え、不可視かつアクセシビリティツリーからも削除されるvisibility
を併用することでメガドロップダウンを実現しています。
display: none;
と異なるのは、visibility: hidden;
だと表示領域が残ってしまうという点です。
※開発者ツール([F12])を使うと確認できます。
表示領域が残ると、レイアウトが無視されず要素の横幅/高さ分スペースが空いた状態になります。
.gnav_mega {
opacity: 0;
visibility: hidden;
transition: 0.3s;
}
.gnav--ul-li:hover .gnav_mega {
opacity: 1;
visibility: visible;
}
opacity: 0;
とvisibility: hidden;
とdisplay: none;
で異なる点をおさらいしましょう。
opacity
の特徴
- トランジション対応
- 値を
0
にしても、見えなくなっているだけなので表示領域は残る - アクセシビリティツリーやスクリーンリーダーに認識される
visibility
の特徴
- トランジション非対応
- 値を
hidden
あるいはcollapase
にしても表示領域は残る - アクセシビリティツリーやスクリーンリーダーに認識されない
display
の特徴
- トランジション非対応
- 値を
none
にすると表示領域が残らない - アクセシビリティツリーやスクリーンリーダーに認識されない
【新しい書き方】display
冒頭で解説した@starting-style
を使用し、display: none;
でのアニメーションを実現したパターンです。opacity
やwidth
などの補間可能プロパティと併用します。
上記で紹介した【従来の方法】とは異なり、こちらは表示領域が完全に消えます。
ここでもう一つの肝となるのが、transition-duration: allow-discrete;
です。
下記のサンプルコードはtransition
のショートハンドなので、この後詳しく説明しますね。
.gnav--ul-li:hover .gnav_mega {
/* トランジション後 */
display: block;
opacity: 1;
/* トランジション前 */
@starting-style {
/* ここにdisplay:none;は書かない */
opacity: 0;
}
}
.gnav_mega {
display: none; /* ここにdisplay:none; */
opacity: 0; /* フェードアウト用 */
transition: opacity 0.3s, display 0.3s allow-discrete; /* allow-discreteでdisplayがトランジション可能に */
}
transition-durationとは?
アニメーションの開始〜終了までの時間を定義するCSSプロパティです。allow-discrete
を指定すると、display
などの離散プロパティのトランジションを可能にします。
※離散プロパティは徐々に変化せず瞬時に切り替わります。
「離散プロパティ」とは?
値を補間できないプロパティのことです。
トランジションの効かないプロパティと考えると簡単です。
diplay: none;
やvisibility: hidden;
の要素をトランジションするには、次のいずれかを使用します。
allow-discrete
値を持つtransition-behavior
プロパティallow-discrete
値はtransition
のショートハンド
/* transitionショートハンド */
transition: opacity 0.3s ease-out, display 0.3s ease-out allow-discrete;
上記のtransition
ショートハンド例では、離散プロパティであるdisplay
のみallow-discrete
を適用しています。
他の値との衝突を防ぐために、allow-discrete
が一番最後になっていることをしっかり確認しましょう!
補間可能プロパティ | color ,opacity ,width ,height ,font-size ,margin ,padding etc |
---|---|
離散プロパティ | display ,visibility ,background-image ,mix-blend-mode ,mask-image etc |
対応ブラウザ
@starting-style
もtransition-duration: allow-discrete;
も、デスクトップ・スマホのすべてのブラウザでサポートされています!
@starting-style


transition-duration


まとめ
いかがでしたでしょうか?
補間可能プロパティと違って少々記述がめんどくさいかもですが、CSSアニメーションの実装を続けていれば「知っていてよかった」と思う日が必ず来ます!
JSなしでアニメーションしたいときに役に立つかもしれませんね^^
コメント