Unformed Building

CSSアニメーションの基礎

公開:
更新:

パーマリンク

今さらながらCSS Animationsの使い方が分かってきたので、プロパティなどを簡単にまとめておきたいと思います。
これを書くにあたって、以下の2つを参考にしました。

  1. CSS Animations Editor’s Draft 25 July 2011
  2. CSS animations - MDN

上のはdev.w3.orgにある、2011年7月25日版のエディターズドラフトです。
ちなみにwww.w3.orgにある仕様は「CSS Animations Module Level 3」です。これを書いている現在、こっちは2009年3月20日版が最新となっています。
基本的に2011年7月25日版のエディターズドラフトをベースに説明したいと思います。なので、現在のブラウザの実装とは異なることもあります。

2つ目のは『Mozilla Developer Network』のドキュメントです。日本語版もあります。
アニメーションに限らず、MDNのドキュメントはとても分かりやすいのでお勧めです。日本語で読めるものも多いです。

これから出てくるプロパティなどは、現在、どのブラウザで使うにしてもベンダー接頭辞が必要ですが、記事内には書きません。

@keyframes

アニメーションを定義する@ルールです。
これを使ってアニメーションの流れを指定することができます。

@keyframes 識別子 {
 from {
   ...
 }
 to {
   ...
 }
}

のように記述します。

識別子は「CSS Values and Units Module Level 3で決められた<identifier>」形式で書く必要があります。
これはASCIIの範囲の文字で、大文字と小文字は区別されます。

キーフレームのセレクタはパーセンテージ、fromまたはtoで記述します。これらはカンマ区切りにより複数指定が可能です。
from0%と等しく、to100%と等しいです。

また、2009年3月20日版のワーキングドラフトでは、from (or 0%)to (or 100%)は必須と書かれていますが、2011年7月25日のエディターズドラフトでは、それらが定義されていない場合はユーザーエージェントが補完する、となっています。
これは最終的にどうなるか分かりませんが、ちゃんと書いておいた方がいいと思います。分かりにくくなりますしね。

この記事で使うアニメーションルールを作りました。
ここから先はこれを使って説明します。

@keyframes left-to-right {
  from {
    left: 0;
  }
  to {
    left: 570px;
  }
}

animation-name

どのアニメーションを使用するか指定します。値には@keyframesで指定した識別子を指定します。

div {
  animation-name: left-to-right;
}

animation-duration

一度のアニメーション周期の完了までの時間を指定します。
値には「CSS Values and Units Module Level 3」で決められた<time>形式で書く必要があります。

デフォルトは0sです。負の値を指定すると、それは0sとして扱われます。
このとき、animation-fill-mode(後述)は適用されていて、その値がbackwardsであった場合、任意の遅延時間内にキーフレームの0%で指定された値が表示されます。forwardsの場合は、100%で指定された値が保持されます。
また、アニメーションイベントも発生します。

では、実際に見てみようと思います。
HTMLは以下のようなものを使います。

<div id="container">
  <div class="test1">1</div>
  <div class="test2">2</div>
  ...
</div>

キーフレーム指定は前述のものを使い、次のような指定をします。
(あんまり関係のない部分は省略しています)

#container > div {
  position      : relative;
  animation-name: left-to-right;
}

.test1 {
  animation-duration: 0.5s;
}

.test2 {
  animation-duration: 1s;
}

.test3 {
  animation-duration: 1.5s;
}

.test4 {
  animation-duration: 2s;
}

animation-durationのデモ

animation-timing-function

どのようなアニメーションを適用するかを指定します。
指定できる値はtransition-timing-functionと同じです。
CSS Transitions」に詳しく説明されています。
一覧にするとこうなります。

ease
cubic-bezier(0.25, 0.1, 0.25, 1)と同じ。
linear
cubic-bezier(0, 0, 1, 1)と同じ。
ease-in
cubic-bezier(0.42, 0, 1, 1)と同じ。
ease-out
cubic-bezier(0, 0, 0.58, 1)と同じ。
ease-in-out
cubic-bezier(0.42, 0, 0.58, 1)と同じ。
cubic-bezier()
3次ベジェ曲線による指定を行います。
step-start
steps(1, start)と同じ。
step-end
steps(1, end)と同じ。
steps()
指定した回数で等間隔に分割して実行されます。

デフォルトはeaseです。

文字だけだと説明しづらいので、cubic-bezier()steps()については「CSS Transitions」に載っている図を参考にしてください。

とりあえず、各指定を使ったサンプルを作りました。
これでどういう動きか分かるかと思います。

.test1 {
  animation-timing-function: ease;
}

.test2 {
  animation-timing-function: linear;
}

.test3 {
  animation-timing-function: ease-in;
}

.test4 {
  animation-timing-function: ease-out;
}

.test5 {
  animation-timing-function: ease-in-out;
}

.test6 {
  animation-timing-function: cubic-bezier(1, 0, 1, 0);
}

.test7 {
  animation-timing-function: step-start;
}

.test8 {
  animation-timing-function: step-end;
}

.test9 {
  animation-timing-function: steps(10, start);
}

.test10 {
  animation-timing-function: steps(10, end);
}

animation-timing-functionのデモ 1

また、これらの関数はアニメーション全体ではなく、キーフレーム間で実行されます。
前出の@keyframes left-to-rightに指定を1つ加えてみると分かりやすいです。
animation-timing-functionの指定は1つ前のデモと同じです。

@keyframes left-to-right {
  from { left: 0; }
  50%  { left: 285px; }
  to   { left: 570px; }
}

animation-timing-functionのデモ 2

正直、cubic-bezier()を動きを予想しながら手書きするのは厳しいというか無理っぽいので、ジェネレータを使ったほうがいいと思います。
そういったものはオンラインにもありますので、いくつか紹介しておきます。

お勧めは上2つです。

animation-iteration-count

アニメーションの実行回数を指定します。
デフォルトは1です。

数値に負の値を指定した場合、0として扱われます。
また、数値の他にinfiniteを指定できます。これを指定するとアニメーションは無限に繰り返されます。

animation-iteration-countのデモ

animation-direction

アニメーションの方向を指定します。
デフォルトはnormalです。

alternateという値を指定すると、奇数回のアニメーションはノーマルな状態で実行され、偶数回のアニメーションは逆方向に実行されます。
このときanimation-timing-functionの指定も逆になります。

animation-iteration-countで使ったデモにanimation-direction: alternateを指定してみました。

animation-directionのデモ

animation-timing-function: easeの動きが逆になっているのが分かるかと思います。

animation-play-state

アニメーションの実行状態を示すプロパティです。
デフォルトはrunningです。

pausedを指定することで、アニメーションを一時停止することができます。
一時停止したアニメーションを再開する場合、停止した時点から再開されます。

また、アニメーションの状態を取得する際にも使用されます。

animation-delay

アニメーションをいつ開始するかを指定するプロパティです。
値は<time>形式で記述します。デフォルトは0sです。

0の指定をした場合、アニメーションが適用されたら即座にアニメーションが実行されます。
1sの場合だと、アニメーションが適用されてから1秒後にアニメーションが始まるわけです。
負の値、たとえば-1sなどは0として扱われ、適用後即実行となりますが、アニメーションが1秒経過した状態から始まります。

下記のようなサンプルを作りましたので、ご確認ください。

.test1 {
  animation-delay: -1s;
}

.test2 {
  animation-delay: 0;
}

.test3 {
  animation-delay: 1s;
}

.test4 {
  animation-delay: 2s;
}

animation-delayのデモ

animation-fill-mode

アニメーションの実行前や後にどういうスタイルを適用するのかを指定します。
指定できる値は以下のようになっています。

none
キーフレームで指定されたスタイルは、アニメーションの前後には適用されません。
forwards
アニメーションの実行後にキーフレームの最後(通常はto, 100%)の指定が適用されます。ただし、animation-directionalternate且つanimation-iteration-countの値が偶数の場合は、キーフレームの最初(通常はfrom, 0%)が適用されます。
backwards
アニメーションが適用されたら即座にキーフレームの最初のスタイル指定を適用します。これはanimation-delayで指定された遅延時間の間も維持されます。
both
forwardsbackwardsの両方が適用されます。アニメーション実行前にはbackwardsが、実行後にはforwardsがあると考えると分かりやすいかと思います。

デフォルトはnoneです。

ちょっと組み合わせがややこしいので、分割してサンプルを作りました。
また、キーフレームの指定も変更しています。
アニメーション適用前はleft: 0の状態です。

@keyframes left-to-right {
  from {
    left: 285px;
  }
  to {
    left: 570px;
  }
}

animation-fill-mode以外のアニメーションの指定は次のようになっています。

/* 共通部分 */
#container > div {
  animation-name           : left-to-right;
  animation-duration       : 3s;
  animation-timing-function: ease;
  animation-direction      : normal;
}

.test1 {
  animation-iteration-count: 1;
  animation-direction      : normal;
  animation-delay          : 0s;
}

.test2 {
  animation-iteration-count: 1;
  animation-direction      : alternate;
  animation-delay          : 0s;
}

.test3 {
  animation-iteration-count: 1;
  animation-direction      : normal;
  animation-delay          : 1s;
}

.test4 {
  animation-iteration-count: 1;
  animation-direction      : alternate;
  animation-delay          : 1s;
}

.test5 {
  animation-iteration-count: 2;
  animation-direction      : normal;
  animation-delay          : 0s;
}

.test6 {
  animation-iteration-count: 2;
  animation-direction      : alternate;
  animation-delay          : 0s;
}

.test7 {
  animation-iteration-count: 2;
  animation-direction      : normal;
  animation-delay          : 1s;
}

.test8 {
  animation-iteration-count: 2;
  animation-direction      : alternate;
  animation-delay          : 1s;
}

animation-fill-mode:none;の場合。
何も指定しないとこれになります。

animation-fill-mode: none デモ

アニメーション適用時(ここではページロード直後)、animation-delayの指定のあるものが最初は左端にあって、アニメーション開始と同時に位置が変更されているのが分かるかと思います。
また、アニメーションが完了すると全ての要素が左端に配置されます。

次はforwardsの場合。

animation-fill-mode: forwards デモ

アニメーション適用時はnoneの指定のときと同じですね。
アニメーション完了時には、それぞれ最後のキーフレームの位置に留まっています。

backwardsの場合。

animation-fill-mode: backwards デモ

アニメーション適用時、遅延のあるものも既にfromの位置に配置されているのが分かります。
完了時はnoneのときと同じです。

bothの場合。

animation-fill-mode: both デモ

アニメーション適用時にはbackwards、完了時にはforwardsと同じような動きをしています。
これで両方の特徴を持っているのが分かります。

animationショートハンドプロパティ

ここまで各プロパティを見てきましたが、結構数があるので書くのが非常に面倒です。
一つ一つ指定していたらこんな感じになります。

div {
  animation-name           : left-to-right;
  animation-duration       : 3s;
  animation-timing-function: linear;
  animation-delay          : 1s;
  animation-iteration-count: 2;
  animation-direction      : normal;
  animation-fill-mode      : forwards;
}

これだけでも多いのに、現状だと更に各ベンダープレフィックスをつけて、1つのプロパティを5種類書かなくてはいけません。計35行です。
(Operaはどうなるか分かりませんが、一応つけるとすると)

これを短縮形で書くことで少し楽になります。
書き方は、2011年7月25日版のエディターズドラフトの時点で、次のようになります。
(見やすくするために改行しています)

animation: name
           duration
           timing-function
           delay
           iteration-count
           direction
           fill-mode

デフォルトは各プロパティに従います。
<time>指定は、1番目がanimation-duration、2番目がanimation-delayとなりますので注意してください。

これに先ほどのものを当てはめると、

div {
  animation: left-to-right 3s linear 1s 2 normal forwards;
}

となります。

ただ、エディターズドラフトを見ると、スラッシュ(/)を使った代替案が書かれています。
それは3s/1sのようなものでduration/delayとするというものです。
このあたりは今後どうなるか分かりませんで気をつけたいところです。

イベント

JavaScript で扱うアニメーションのイベントです。

animationstart
アニメーション開始時のイベントです。
animation-delayが指定されている場合は、遅延時間が完了してから発生します。
animationend
アニメーション終了時のイベントです。アニメーションが完了したときに発生します。
animationiteration
animation-iteration-count1より大きい場合にのみ発生します。
これはアニメーションが1周するごとに発生します。

現在、Firefoxでは上記の通り全て小文字で接頭辞なしの記述ですが、
WebkitブラウザではwebkitAnimationStart, webkitAnimationEnd, webkitAnimationIteration、IE 10ではMSAnimationStart, MSAnimationEnd, MSAnimationIterationとなっています。

最後に

最後まで読んでくださってありがとうございます。お疲れ様でした。

この記事はあくまでも2011年10月序盤で確認できる仕様を元にしたものであり、今後変更がある可能性があります。
また、説明の足りない部分や解釈の間違い、英文の誤読がある可能性もあります。

ですので、一度は仕様を見ておいてほしいと思います。