2020/11 初心者のためのCSSアニメーション入門
こんにちは、大阪事業所所属の瀬戸です。今回は、ずっと苦手意識のあったCSSアニメーションについて自分で調べてわかったことや、上長に質問して理解できたことを、簡単にまとめようと思います。
「HTMLやCSSを書くことには慣れてきたけど、アニメーションは全然わからない...」「トランジションとCSSアニメーションはどう違うの?使い分けは?」など、アニメーションに苦手意識を持った人の助けになれば幸いです。
トランジション と アニメーション
CSSでアニメーションを実装するには、CSS Transition と CSS Animation の2種類があります。イメージとしては、CSS Transition はお手軽アニメーション、CSS Animation は本格アニメーションという感じです。両者の使い分けについてはあとで解説しますので、先にCSS Transitionについて見ていきます。
CSS Transition
Transitionは英語で「移行」を意味しますが、CSS Transitionはプロパティの変更を検知し、変化前の状態から一定時間で緩やかに見た目を変化させることができます。変化していく途中の状態を細かく指定することはできません。後述するトランジションのプロパティの指定に合わせて、CSSがよしなにアニメーションしてくれます。
CSS Transitionでは以下のプロパティを使って、アニメーションを実装していきます。
- transition-duration
- transition-property
- transition-timing-function
- transition-delay
- transition
transition-duration
アニメーション開始から終了までにかかる時間を指定します。指定できる単位はs(秒)、ms(ミリ秒)です。 初期値は0ですが、この場合はアニメーションは発生せず、すぐに変更が適用されます。
<div class="box"><div>
.box{
background-color: yellow;
height: 100px;
/* 変化前の幅 */
width: 200px;
transition-duration: 2s;
}
.box:hover{
/* 変化後の幅 */
width: 500px;
}
transition-property
アニメーションを適用するプロパティを指定します。ここで指定されたプロパティのみ、トランジションが適用されます。初期値はall
ですが、all
の場合はトランジションが適用できるすべてのプロパティに作用します。
個別にプロパティを指定する場合は、トランジションを適用したいプロパティ名を書きます。複数ある場合は、カンマで区切ります。
widthのみ指定
<div class="box1"></div>
width, heightを指定
<div class="box2"></div>
all
<div class="box3"></div>
div {
margin-bottom: 1rem;
width: 100px;
height: 100px;
background-color: yellow;
transition-duration: 2s;
}
div:hover{
width: 500px;
height: 200px;
background-color: orange;
}
.box1 {
transition-property: width;
}
.box2 {
transition-property: width, height;
}
.box3 {
transition-property: all;
}
それぞれ指定したプロパティにのみアニメーションが適用され、それ以外のプロパティは瞬時に変更が適用されていることがわかると思います。
transition-timing-function
だんだん早くなるのか、最初と最後はゆっくりになるのかなど、どのように変化していくのか、その変化の具合(イージング)を指定します。イージングの変化の仕方は大きく分けて以下の4つです。
- linear : 等速で変化する
- ease-in : 徐々に加速する
- ease-out : 徐々に減速する
- ease-in-out : 加速してから減速する
イージングを指定するときは以下のサイトが参考になるかと思います。
イージング関数チートシート https://easings.net/ja
transition-delay
変化が始まるまでの時間を指定します。transition-duration
と同様に、単位は s(秒)、ms(ミリ秒)が使えます。0s
もしくは0ms
のときはプロパティの変更を検知するとすぐにアニメーションが始まります。
1秒後にアニメーション
<div class="box"></div>
.box {
width: 100px;
height: 100px;
background-color: yellow;
transition-duration: 2s;
transition-delay: 1s;
}
.box:hover{
width: 500px;
}
transition
transition
プロパティは、上記4つのプロパティをまとめて指定できるショートハンドプロパティです。
transition-property
, transition-duration
, transition-timing-function
, transition-delay
の順番で記述します。
transition: width 1s;
transition: width 1s ease-in;
transition: width 1s ease-in 0.5s;
Q. 変化前と変化後、どっちに指定するの?
両方とも指定できます。ただし、変化前にtransition
を指定した場合と、変化後にtransition
を指定した場合で少し挙動が異なります。
変化前にtransition
<div class="box1"></div>
変化後にtransition
<div class="box2"></div>
div {
height: 100px;
background-color: yellow;
margin-bottom: 1rem;
}
.box1 {
width: 100px;
transition: width 2s;
}
.box1:hover {
width: 500px;
}
.box2 {
width: 100px;
}
.box2:hover {
width: 500px;
transition: width 2s;
}
この例を見ていただくと、幅が広がるときはどちらも全く同じ変化の仕方ですが、元に戻るときのアニメーションが異なります。
変化前にtransitionを指定したほうは元に戻るときもアニメーションされますが、変化後にtransitionを指定したほうは元に戻るときにアニメーションが適用されず、一瞬で元の状態に戻ります。
Q. どうやってアニメーションを発生させるの?
:hover
などの擬似セレクタを使う方法と、JavaScriptでクラスの付け替えをする方法があります。これにより、ユーザーの操作によってプロパティの変更を検知し、アニメーションさせることができます。
擬似セレクタ(hover)
<div class="box1"></div>
JavaScriptでクラスの付与・削除
<div id="box2" class="box2"></div>
const box2 = document.getElementById('box2');
box2.addEventListener('click', () => {
if(box2.classList.contains('big')){
box2.classList.remove('big');
}else{
box2.classList.add('big');
}
})
div {
background-color: yellow;
margin-bottom: 1rem;
}
.box1 {
width: 100px;
height: 100px;
transition: all 2s;
}
/* 変化後の状態 */
.box1:hover {
width: 200px;
height: 200px;
}
.box2 {
width: 100px;
height: 100px;
transition: all 2s;
}
/* 変化後の状態 */
.big {
width: 200px;
height: 200px;
}
パッと見はわかりにくいですが、上の例はマウスを要素にhoverすることでアニメーションが発生しています。下の例は、要素をクリックするたびにJavaScriptでbig
クラスを付与・削除しています。
こうすることでアニメーションを発生させることはできますが、この例のように、transition
もしくはtransition-property
で指定したプロパティがどう変わるのかを指定しなければアニメーションが発生しないので注意です。
CSS Animation
CSS Animation は CSS Transition よりも細かいアニメーションの設定が可能です。CSS Transitionではhover
やクラスの追加・削除などのアニメーション開始のきっかけが必要でしたが、CSS Animationの場合はきっかけがなくてもアニメーションさせることができます。つまり、読み込み後すぐにアニメーションが発生します。
CSSアニメーションは2つの要素で構成されています。一つはCSS Transitionと同じようにアニメーション時間、変化速度など、アニメーションについて記述する部分で、もう一つはスタイルの指定です。
CSS Animation では、アニメーションの指定をする前に@keyframes
を使用して任意の地点でのスタイルを定義(キーフレームアニメーションと言います)しておく必要があります。
@keyframes scale {
0% {
width: 100px;
}
50% {
width: 400px;
}
100% {
width: 300px;
}
}
@keyframes
の横にscale
とありますが、これはこのアニメーションの名前です。変数を定義するような感覚です。
この例では、アニメーション開始時の幅が100px、半分の時間が経過したタイミングでの幅が400px、終了時の幅が300pxとなるよう定義しています。しかし、これだけだと特定のタイミング(キーフレーム)でのスタイルを定義しただけなので、まだアニメーションはできません。
これをアニメーションさせるためには、以下のプロパティを使用してどのようにアニメーションさせるかを指定します。
- animation-name
- animation-duration
- animation-timing-function
- animation-delay
- animation-iteration-count
- animation-direction
- animation-fill-mode
- animation-play-state
- animation
CSS Transition でも似たようなプロパティがありますが、使い方は大体同じです。ここではそれ以外のプロパティについて説明していこうと思います。
animation-name
animation-name
は、@keyframes
で定義したアニメーションの名前を指定します。
animation-name: scale;
animation-iteration-count
CSS Transition では、プロパティの変更があったときの1回だけしかアニメーションが発生しません。しかし、CSS Animation は何回実行するかを指定することができます。初期値は1です。
無限に実行したい場合は、値にinfinite
を指定します。
1回
<div class="box1"></div>
3回
<div class="box2"></div>
∞回(infiniteを指定)
<div class="box3"></div>
div {
background-color: yellow;
margin-bottom: 1rem;
width: 100px;
height: 100px;
animation-name: scale;
animation-duration: 3s;
}
.box1 {
animation-iteration-count: 1;
}
.box2 {
animation-iteration-count: 3;
}
.box3 {
animation-iteration-count: infinite;
}
上のgif画像は5回ループしたら最初から再生されるようになっています。animation-iteration-count
の指定によるものではないのでお気をつけください。
animation-direction
animation-direction
は、アニメーションの再生方向を指定することができます。再生方向は以下の4通りです。
- normal:毎回順方向で再生
- reverse:毎回逆方向から再生
- alternate:順方向から始まり、順方向と逆方向を交互に繰り返す
- alternate-reverse:逆方向から始まり、逆方向と順方向を交互に繰り返す
animation-fill-mode
アニメーション開始前と終了後に、@keyframes
で指定したプロパティを適用するかどうかを指定します。
・none:開始前、終了後にはアニメーションのスタイルは適用されない(初期値) ・forwards:終了後は終了時のスタイルを適用 ・backwards:開始前に開始時のスタイルを適用 ・both:開始前には開始時のスタイル、終了後は終了時のスタイルを適用
none
<div class="box1"></div>
forwards
<div class="box2"></div>
backwards
<div class="box3"></div>
both
<div class="box4"></div>
div {
background-color: yellow;
margin-bottom: 1rem;
width: 200px;
height: 100px;
animation-name: scale;
animation-duration: 3s;
animation-delay: 3s;
}
.box1 {
animation-fill-mode: none;
}
.box2 {
animation-fill-mode: forwards;
}
.box3 {
animation-fill-mode: backwards;
}
.box4 {
animation-fill-mode: both;
}
開始前、終了後にどの時点のスタイルが適用されているかわかりやすいよう、あえて色も変えています。
animation-play-state
animation-play-state
は、アニメーションが実行中か停止中かを指定します。running
の場合は実行し、paused
の場合は停止します。paused
からrunning
に切り替わる場合は停止したところから再開します。
<div class="running" id="box"></div>
<button id="button">一時停止</button>
const button = document.getElementById('button');
button.addEventListener('click', ()=>{
const box = document.getElementById('box');
if(box.classList.contains('running')){
box.classList.remove('running');
box.classList.add('paused')
button.innerText = '再生する';
}else{
box.classList.remove('paused');
box.classList.add('running')
button.innerText = '一時停止';
}
})
div {
background-color: yellow;
margin-bottom: 1rem;
width: 100px;
height: 100px;
animation-name: scale;
animation-duration: 3s;
animation-iteration-count: infinite;
}
.running {
animation-play-state: running;
}
.paused {
animation-play-state: paused;
}
animation
animation
はこれまでのプロパティをまとめて指定できる、ショートハンドプロパティです。transition
とは違い各プロパティは順不同で指定できます。ただ、animation-duration
とanimation-delay
は両方とも秒数を指定するので、最初に指定されたほうがanimation-duration
の秒数として解釈されます。
Q. CSS Transition と CSS Animation の使い分けは?
シンプルなアニメーションであれば CSS Transition、少し凝ったアニメーションにしたい場合は CSS Animationを使います。 ただ、シンプルなアニメーションであっても、フェードインのように同じアニメーションがいろいろなところで必要な場合は、CSS Animationでアニメーションを定義しておいた方が楽になる場合もあります。
Q. JavaScriptのアニメーションは?
まずはCSS Transitionで実装できないか検討してみて、それがダメだったらCSS Animation、それでも難しい場合や、よりリッチなWebサイトを作り込みたいときはJavaScriptも使う、という感じで作っていくのがいいかと思います。
Q. どこでどんなアニメーションをいれたらいいかわからない!
アニメーションは、基本的にはユーザーの操作に対するフィードバックが目的です。視覚的な動きを取り入れることにより、今どんな状態なのか、どんな変化が起きたのかをよりわかりやすくユーザーに伝えることができます。 UIを考える上で大切な基本原則については、以下のサイトにわかりやすくまとめられています
モバイルアプリのUI設計に大切な、7つの基本アニメーションまとめ https://photoshopvip.net/88490
まとめ
僕自身が学習する上でつまづいたポイントも盛り込んでみましたが、いかがだったでしょうか。これからアニメーションについて学習する人は、まずは CSS Transition に慣れることをおすすめします。少しでもアニメーション学習の助けになれば幸いです。