前提
この記事は極力VueのAPIとCSSだけでTransitionアニメーションを実装するという趣旨の元執筆しています。
またtransitionプロパティ
とVueある程度知っていると仮定した上で話を進めていきます。
よく知らないという方はこちらを閲覧してから、この記事を閲覧することをオススメします。
注意
この記事はデモにCodePenを使用していますが、transitionに必要なCSSを判別しやすくするため、transition関連のスタイルはCSSの欄に、それ以外のスタイルはHTMLの<style>
タグに書いています。
あまり褒められたやり方ではないので、本番環境では真似しないでください
まず初めに
Vueではv-if
かv-show
に真偽値を入れてやることで、要素の表示と非表示を切り替えることができます。
しかし、その要素にCSSでtransitionプロパティ
を設定してやっても、上手く実行されません。
Vueには<transition>
というラッパーコンポーネントが用意されていて、これでtransitionさせたい要素を囲むことで上手くtransitionが実行されます。
詳しくはこちらを参照してください => Enter/Leave とトランジション一覧
<template>
<transition name="fade">
<div v-if="show">
Fade
</div>
</transition>
</template>
<transition>
コンポーネントで囲むことでCSSクラスが付与されます。
<style scoped>
.fade-enter-active, .fade-leave-active {
/* 表示されている際のCSSはこのブロックに記述 */
}
.fade-enter, .fade-leave-to {
/* 非表示の際のCSSはこのブロックに記述 */
}
</style>
付与されるクラス名は<transition>
のname
で指定した値によって変わります。
具体的には上記のクラス名のfade
の部分がそれに当たります。
例えばname
に指定した値がslide
だった場合は
<style scoped>
.slide-enter-active, .slide-leave-active {
/* 表示されている際のCSSはこのブロックに記述 */
}
.slide-enter, .slide-leave-to {
/* 非表示の際のCSSはこのブロックに記述 */
}
</style>
の様になります。
ちなみにラッパーコンポーネントは、最終的なDOM
には表示されないので、階層に気を付けなくても大丈夫です!
Fade
FadeはTransitionアニメーションの中でも非常にシンプルでポピュラーな物です。
.fade-enter-active, .fade-leave-active {
will-change: opacity;
transition: opacity 225ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
}
.fade-enter, .fade-leave-to {
opacity: 0
}
Fadeの実装に必要なスタイルは上記の様になります。
will-changeについて
Fadeを実装する上で、このプロパティは必要ありません。
ではなぜこのプロパティが記述されているのか?
will-change
はブラウザにどの要素の変更がよそされるのかを通知し、ブラウザはその通知を元に最適化を行います。
これにより応答パフォーマンスが向上します。
will-changeの使用に関する注意
今回は紹介の為に使用しましたが、will-change
はいいことばかりではありません。
近年のブラウザは何も指定せずともできる限り、最適化を行っており、will-change
をいたずら複数指定することは、必要以上のマシンリソースを消費してしまいます。
あくまで、ページの表示が遅いサイトの応答パフォーマンスを向上させるための最終手段として使用することをオススメします。
詳しくはこちらをご覧ください
Top Slide
これから紹介するslide系TransitionはWebページにちょっとした遊び心を加えます。
ただし、使いすぎるとユーザーに鬱陶しさを与えます。
使いどころとしてはトースト通知などがあるでしょう。
.top-enter-active, .top-leave-active {
transform: translate(0px, 0px);
transition: transform 225ms cubic-bezier(0, 0, 0.2, 1) 0ms;
}
.top-enter, .top-leave-to {
transform: translateY(-100vh) translateY(0px);
}
transform
slide系transitionではtransform
プロパティが重要になってきます。
transform
プロパティはその名前の通り要素の回転、拡大縮小、傾斜、移動を行うことができます。
詳しくはCSS3クイックリファレンスとMDN web docsをご覧ください
vh
とは?
上記のCSS
をコピペで使用する場合は注意が必要です。
.top-enter, .top-leave-to {
transform: translateY(-100vh) translateY(0px);
}
で-100vh
と指定していますが、このvh
を見慣れないビギナーの方もいると思います。
このvh
とはviewport height
の略称で、要は表示されている範囲をさしています。
上記の例で言えば100vh
はview portの高さと同じ高さの数値を得る。所謂パーセンテージなのです。
これを正常に動作させる為にはhtml
の<head>
要素の中に以下の<meta>
要素を記述する必要があります。
<meta name="viewport" content="width=device-width, initial-scale=1.0">
最近の高性能なエディタを使っていればhtml
ファイルを作ったらすでに書いてあったという人もいると思います。
viewportを元に計算する単位は全部で4つ存在します。
単位 | 略称元 | 効果 |
---|---|---|
vh | viewport height | ビューポートの高さに対する割合 |
vw | viewport width | ビューポートの幅に対する割合 |
vmin | viewport minimum | ビューポートの幅と高さのうち、値が小さい方に対する割合 |
vmax | viewport max | ビューポートの幅と高さのうち、値が大きい方に対する割合 |
%
と何が違うの?
誰もが一度は使う%
は親の値に依存しています。
例えば親がheight: 400px
だとすれば、%
は親のheight
を元に計算されてしまいます。
そこで、どの階層にいても親要素に関係なく、Webページの表示領域のheight
とwidth
を元に計算したいと行った場合にvh
やvw
を使うと期待通りの効果が得られるでしょう。
Top Left Slide
.top-left-enter-active, .top-left-leave-active {
transform: translate(0px, 0px);
transition: transform 225ms cubic-bezier(0, 0, 0.2, 1) 0ms;
}
.top-left-enter, .top-left-leave-to {
transform: translateY(-100vh) translateX(-100vh);
}
Top Right Slide
.top-right-enter-active, .top-right-leave-active {
transform: translate(0px, 0px);
transition: transform 225ms cubic-bezier(0, 0, 0.2, 1) 0ms;
}
.top-right-enter, .top-right-leave-to {
transform: translateY(-100vh) translateX(100vh);
}
Bottom Slide
.bottom-enter-active, .bottom-leave-active {
transform: translate(0px, 0px);
transition: transform 225ms cubic-bezier(0, 0, 0.2, 1) 0ms;
}
.bottom-enter, .bottom-leave-to {
transform: translateY(100vh) translateY(0px);
}
Bottom Left Slide
.bottom-left-enter-active, .bottom-left-leave-active {
transform: translate(0px, 0px);
transition: transform 225ms cubic-bezier(0, 0, 0.2, 1) 0ms;
}
.bottom-left-enter, .bottom-left-leave-to {
transform: translateY(100vh) translateX(-100vh);
}
Bottom Right Slide
.bottom-right-enter-active, .bottom-right-leave-active {
transform: translate(0px, 0px);
transition: transform 225ms cubic-bezier(0, 0, 0.2, 1) 0ms;
}
.bottom-right-enter, .bottom-right-leave-to {
transform: translateY(100vh) translateX(100vh);
}
Left Slide
.left-enter-active, .left-leave-active {
transform: translate(0px, 0px);
transition: transform 225ms cubic-bezier(0, 0, 0.2, 1) 0ms;
}
.left-enter, .left-leave-to {
transform: translateX(-100vw) translateX(0px);
}
Right Slide
.right-enter-active, .right-leave-active {
transform: translate(0px, 0px);
transition: transform 225ms cubic-bezier(0, 0, 0.2, 1) 0ms;
}
.right-enter, .right-leave-to {
transform: translateX(100vw) translateX(0px);
}
demo(CodePen)
See the Pen CSS Transition by マテリアルお兄さん (@nexus0831) on CodePen.
最後に
いかがだったでしょうか?
基本となるFade
と全部で8方向からのSlide
を今回は実装してみました。
ダイアログやアラート、通知を出す際にこれらが使えると、少しばかりユーザーに楽しさを与えることができるでしょう。
少なくとも私は何度も押してしまう位には好きです(笑)