Vue には v-if
などの条件付き描画を使ってコンポーネントを表示/非表示する際に CSS の transition や animation の動きを付与できる transition ラッパーコンポーネントというものがあります。今回は表示・非表示で非対称な動きをする Vue transition と CSS の実装についてメモします。
時間差でフェードイン、クリック時にフェードアウトするカード
次のようなカードの要素を作ってみます。なおカードの上にあるボタンは動作確認用のものなので、記事の本題とは関係ありません。
See the Pen vue-transition-asynchronously-fade-in/out-1 by hamakou108 (@hamakou108) on CodePen.
このカードは Vue インスタンスがマウントされてから3秒後に表示され、クリックするとフェードアウトします。
実装を見ると分かる通り、 enter-active-class と leave-active-class に別々の CSS を当てることで非対称なトランジション・アニメーションを実現しています。 leave-active-class の方は transition を利用していますが、トランジション完了時の opacity の値を leave-to-class に指定することでフェードアウトを実現できます。
時間差でフェードインした後に時間差でフェードアウトするカード
次に少しひねったパターンとして、フェードインしてしばらく時間が経つと勝手に消えるカードを作ってみます。
クリック時にフェードアウトする動作も残しておきます。
See the Pen vue-transition-asynchronously-fade-in/out-2 by hamakou108 (@hamakou108) on CodePen.
enter-active-class が利用する @keyframes
を変更して自然にフェードアウトするようにしました。
ただ @keyframes
の変更だけだと幾つか問題があります。
まず enter-active-class に指定したスタイルはアニメーション終了後に削除されます。
これにより、アニメーション終了後は .card
に指定したスタイルがそのまま当たるため、 visibility: visible; opacity: 1
となってフェードアウトさせたカードが再表示されてしまいます。
これを避けるため .card
には visibility: hidden; opacity: 0;
を設定しています。
さらにこの設定によって今度は leave-active-class のトランジションの初期状態が visibility: hidden; opacity: 0;
となるため、クリック時はフェードアウトではなく瞬時に消えてしまうような動きになってしまいます。
これを避けるため .fade-leave-active
には visibility: visible; opacity: 1;
を指定して、表示された状態からトランジションが開始するようにしています。
まとめ
Vue transition を使って非対称なトランジション・アニメーションを行う際、少しの動作の変更が細かな部分に影響してきます。
特に entering 終了後および leaving 開始前の状態がどうなっているべきかを考慮して CSS を当てていくことが重要になりそうです。