【CSS】 animationとkeyframeの種類
CSSでは、transition以外にもkeyframeを用いた複雑なアニメーションを作成できます。どの時間帯にどのような状態なのかを細かく指定できます。
目次
animationの方法
CSSでアニメーションするには、keyframes
とanimation
プロパティの2つを組み合わせます。
keyframes
でどのような時刻にどのような状態かを指定し、animation
プロパティで時刻の変化の仕方を指定します。
See the Pen css animation keyframe by Totori (@souki202) on CodePen.
keyframes
keyframes
には、時刻ごとの状態を指定します。時刻はパーセンテージで指定します。つまり、0%
はアニメーション開始の時刻、100%はアニメーション終了の時刻ということです。
例えば、
@keyframes slidein { 0% { margin-left: 0; } 100% { margin-left: 300px; } }
とすると、開始した瞬間はmargin-left: 0;
の状態、終了時にはmargin-left: 300px;
の状態になります。
0%
の代わりにfrom
, 100%
の代わりにto
と書くこともできます。
keyframeを増やす場合も同様にパーセンテージを指定します。
@keyframes slidein { 0% { margin-left: 0; } 75% { margin-left: 400px; } 100% { margin-left: 300px; } }
上の例だと、75%
のタイミングでは400px
分移動し、100%
のタイミングで300px
に戻る、という動作になります。
animationプロパティ
animationプロパティは非常に多くの指定方法があるため、いくつかのパターンだけ把握しておくと良いです。下で紹介するもの以外にも、識別できる内容と順序であれば動作します。
p { /* アニメーション時間 | アニメーション種類 | 最初のアニメーションまでの待ち時間 | ループ回数 | 時刻の向き | 開始と終了の状態 | 再生の状態 | keyframes名 */ animation: 3s ease-in 1s infinite normal both running slidein; /* keyframes名 | 時間 | 種類 | 開始待ち時間 */ animation: slidein 3s linear 1s; /* keyframes名 | 時間 | 種類 | ループ回数 */ animation: slidein 3s ease-in infinite; /* keyframes名 | 時間 */ animation: slidein 3s; }
複数のアニメーションを指定する場合はカンマで区切ります。
p { /* keyframes名 | 時間 */ animation: slidein 3s, bigger 1s; }
ここで、複数のアニメーションを指定した場合、それぞれのアニメーションは完全に別々のパラメータで再生されます。再生自体は同時にできますが、アニメーションの状態の管理は別々ということです。
個別指定
他のCSSのプロパティと同じように、それぞれの値は個別で指定できます。
animation-name
アニメーション名を指定します。これは、keyframes
に付けた名前を指定します。
p { animation-name: sample-anim; /* 複数のアニメーションを使用する */ animation-name: sample-anim, test-1; }
animation-duration
アニメーションの時間を指定します。
p { animation-duration: 3s; animation-duration: 200ms; /* sample-animが3s, test-1が100ms */ animation-name: sample-anim, test-1; animation-duration: 3s, 100ms; }
animation-timing-function
アニメーションの種類です。線形に変化するのか、最初はゆっくりでだんだん早くなるのかなどを指定できます。これはtransitionに指定したものと同じ挙動になります。
細かいアニメーションの動きは下の記事を参考にしてください。
p { animation-timing-function: ease; /* 完了と終了がなめらか */ animation-timing-function: ease-in; /* ゆっくり始まる */ animation-timing-function: ease-out; /* ゆっくり終わる */ animation-timing-function: ease-in-out; /* ゆっくり始まり, ゆっくり終わる */ animation-timing-function: linear; /* 一定の速度 */ animation-timing-function: step-start; /* アニメーション開始直後に変化 */ animation-timing-function: step-end; /* アニメーション終了時に変化 */ animation-timing-function: steps(4, jump-start); /* 開始時に最初のジャンプ */ animation-timing-function: steps(10, jump-end); /* 終了時に最後のジャンプ (1回目のジャンプが遅れる) */ animation-timing-function: steps(20, jump-none);/* startとendの中間のタイミングでジャンプ */ animation-timing-function: steps(5, jump-both); /* 1回目が少し遅れ(jump-endと同じ), 最後が止まった状態で終わる(jump-start) */ animation-timing-function: steps(6, start); /* jump-startと同じ */ animation-timing-function: steps(8, end); /* jump-endと同じ */ animation-timing-function: steps(6, step-start); /* jump-startと同じ */ animation-timing-function: steps(8, step-end); /* jump-endと同じ */ animation-timing-function: cubic-bezier(0.1, 0.7, 1.0, 0.1); /* ベジェ曲線で指定 */ }
ここで、linear以外を指定したときに注意があります。
linear
以外では開始が遅い、終了が遅いなどあります。このとき、アニメーションは0~100%がそうなるのではなく、各keyframeごとにそのような挙動になります。
See the Pen Untitled by Totori (@souki202) on CodePen.
カクカクしていますね。各keyframe間でease-in
の挙動になっています。現状は回避する方法はないため、区切る際は全く区切らないようにするか、linearにした上でたくさん区切って動きを近似するなどの工夫が必要です。アニメーション量や速度によりますが、6分割くらいしておけばlinear
でease
系の動きを近似してもほぼ気が付きません。
animation-delay
アニメーションが開始するまでの時間です。ループしてからは無視されます。
また、負数を指定するとアニメーションの途中から開始することができます。
p { animation-delay: 3s; animation-delay: 100s; animation-delay: 0; /* 2秒経過した時点からスタート */ animation-delay: -2s; }
animation-direction
アニメーションの再生の方向です。普通に再生なのか、逆再生なのか、再生と逆再生を繰り返すのか、などを指定できます。
See the Pen css animation direction by Totori (@souki202) on CodePen.
p { animation-direction: normal; animation-direction: reverse; animation-direction: alternate; animation-direction: alternate-reverse; /* アニメーションが複数の場合 */ animation-direction: normal, alternate; }
値 | 意味 |
---|---|
normal | 順方向に再生 |
reverse | 逆方向に再生。アニメーションの種類 (ease-out など) も全て逆再生状態になります。 |
alternate | 順方向と逆方向を交互に再生 |
alternate-reverse | 逆方向と順方向を交互に再生 |
animation-iteration-count
ループ回数を指定します。0
の場合は一度も再生されず、infinite
なら無限にループします。1.5
などの小数がついたら、アニメーションは途中で終わります。つまり、1.5
なら2回目のちょうど半分まで再生が行われます。
p { animation-iteration-count: infinite; /* 再生しない */ animation-iteration-count: 0; /* 初期値 */ animation-iteration-count: 1; /* 2回と、3回目の40%地点まで再生 */ animation-iteration-count: 2.4; /* 複数のアニメーションがある場合 */ animation-iteration-count: 1, 2, 2.4; }
animation-fill-mode
アニメーションの実行前後にどのような状態になっているかを指定します。この状態には、アニメーションの方向が影響します。
forwards
の場合、最後の状態が計算されます。順方向なら最後(100%)、逆方向なら最初(0%)が最終的な状態になります。主にループが完全に終了後に影響します。
backwards
の場合、最初の状態が計算されます。順方向なら最初(0%)、逆方向なら最後(100%)が最初の状態になります。これは、主にanimation-delay
が指定されているときに影響します。
both
の場合、forwards
とbackwards
両方が適用されます。
デフォルトはnone
です。none
は、アニメーションの状態ではなく、その他のCSSの状態で決まります。(つまり、アニメーションが終わったらアニメーションの状態は破棄される)
p { animation-fill-mode: none; animation-fill-mode: forwards; animation-fill-mode: backwards; animation-fill-mode: both; }
See the Pen css animation fillmode by Totori (@souki202) on CodePen.
再生がalternate
の場合は、アニメーションが終わったときの再生の方向によって決まります。
animation-play-state
再生しているか、停止しているかを指定します。ここで、停止や再生時に時間は戻りません。
p { /* 停止 */ animation-play-state: paused; /* 再生 */ animation-play-state: running; }
See the Pen css animation playstate by Totori (@souki202) on CodePen.
アニメーションサンプル
下の例は、複数のアニメーションを使用した例です。光っている部分は四角いブロック要素ですが、それのscale
の変化とopacity
の変化を別々でアニメーションさせています。
See the Pen practice button2 by Totori (@souki202) on CodePen.
まとめ
複数のアニメーションを組み合わせたり、hover時にだけアニメーションを付けるなどで、非常に高度なアニメーションをCSSだけで組むことができます。少し複雑ですが、重要なプロパティなので使えるようになりましょう!
