こんにちは、さち です。
先日、ウェブサイトでアニメーションをさせる方法について、調べる機会がありました。
その時に、CSS の「transition」「animation」を使う方法も知ったのですが、これが結構複雑で理解して使うには多くの知識が必要でした。
今回は、その時に学習した内容を徹底的にまとめました。多くのサンプルも付けて分かりやすい解説を心がけたので、少しでも読んでくれた人のお役に立てれば幸いです。
jQuery(JavaScript) でアニメーション
jQuery(JavaScript)の「animate」を使ってアニメーションさせます。JavaScript で CSS の値を変更させて動かします。
サンプルコード
<button type="button">クリックで移動</button> <div></div>
div { position: relative; left: 0px; width: 75px; height: 75px; background-color: #F00; }
$('button').click(function() { $('div').animate({'left':'200px'}, 2000, 'swing'); });
構造の解説
$('div').animate( {'プロパティ名':'アニメーション終点の値'}, アニメーションにかける時間, '変化の速度' );
プロパティ名
アニメーションさせる CSS プロパティを指定。
width, margin など数値を扱うものなら何でもOK。コンマで区切って複数指定可能。
{'left':'200px'} //1つだけ指定 {'left':'200px', 'width':'150px', 'height':'150px'} //複数指定
アニメーション終点の値
アニメーションの終点の値を指定。単位は、「px」以外に「em」「%」でもOK。
相対的な変化を指定することも可能。
{'left':'200px'} //「200px」の位置に移動する(絶対移動) {'left':'+=50px'} //現在位置から右に「50px」移動する(相対移動) {'left':'-=30px'} //現在位置から左に「30px」移動する(相対移動)
アニメーションにかける時間
アニメーションにかける時間を指定。数値の単位は「ミリ秒」。
数値の代わりに「slow(=600)」「fast(=200)」も利用可能。
初期値は400ミリ秒。
animate({'left':'200px'}, 1000, 'swing') //1秒かけてアニメーション animate({'left':'200px'}, 'slow', 'swing') //0.6秒かけてアニメーション
変化の速度
アニメーションの変化の速度を指定。
「swing」「linear」の2種類から選択可能。初期値は swing。
animate({'left':'200px'}, 500, 'swing'); //加速→減速 animate({'left':'200px'}, 500, 'linear'); //一定速度
長所・短所
- 恐らく、コードの行数が一番少なく手間がかからない
- jQuery がサポートしているブラウザすべてで動くため
ブラウザ毎の実装の違いを気にする必要がない
- jQuery の導入が必要(大した手間ではないけれど)
- CPUが非力だと動きがカクつく(特に、スマホで顕著)
transition(CSS)でアニメーション
CSS の「transition」を使ってアニメーションさせます。
アニメーション用に「move」というクラスを作り、そこに「transition」でアニメーションの制御を記述。それを div に追加することでアニメーションを発動します。
サンプルコード
<button type="button">クリックで移動</button> <div></div>
/* アニメーション前の状態 */ div { position: relative; left: 0px; width: 75px; height: 75px; background-color: #F00; } /* アニメーション後の状態 */ .move { left: 200px; transition-property: left; transition-duration: 2s; transition-timing-function: ease-in-out; transition-delay: 0s; }
$('button').click(function() { $('div').addClass('move'); //divにクラス「move」を追加 });
構造の解説
.move { プロパティ名: アニメーション終点の値; transition-property: アニメーションさせるプロパティ名; transition-duration: アニメーションにかける時間; transition-timing-function: 変化の速度; transition-delay: 開始を遅らせる時間; }
transition-property(アニメーションさせるプロパティ名)
アニメーションさせるプロパティ名を指定。
width, margin など数値を扱うものなら何でもOK。コンマで区切って複数指定可能。
「all」で全プロパティをアニメーション。初期値は「all」。
transition-property: left; /* 1つだけ指定 */ transition-property: left, width, height; /* 複数指定 */ transition-property: all; /* すべてのプロパティを指定 */
transition-duration(アニメーションにかける時間)
アニメーションにかける時間を指定。
秒[s] または ミリ秒[ms] で指定(1秒=1000ミリ秒)。初期値は0秒。
Firefox では「0秒」でも単位省略不可。
transition-duration: 2s; /* 2秒かけてアニメーション */ transition-duration: 2500ms; /* 2.5秒かけてアニメーション */
transition-timing-function(変化の速度)
アニメーションの変化の速度を指定。
「ease」「ease-in」「ease-out」「ease-in-out」「linear」「step-start」「step-end」の7種。
「steps(ステップ数,startまたはend)」でステップ数分だけ段階的に変化。
「cubic-bezier」で3次ベジェでの数値指定も可能(解説省略)。初期値はease。
transition-timing-function: ease; /* 加速→減速 */ transition-timing-function: ease-in; /* 加速 */ transition-timing-function: ease-out; /* 減速 */ transition-timing-function: ease-in-out; /* easeよりゆっくり加速→減速 */ transition-timing-function: linear; /* 一定速度 */ transition-timing-function: step-start; /* 即終点 */ transition-timing-function: step-end; /* 終点直前まで始点を維持 */ transition-timing-function: steps(5,start); /* 5段変化(始点で即変化) */ transition-timing-function: steps(5,end); /* 5段変化(始点を維持) */
transition-delay(開始を遅らせる時間)
アニメーションの開始を遅らせる時間を指定。
秒[s] または ミリ秒[ms] で指定(1秒=1000ミリ秒)。初期値は0秒。
Firefox では「0秒」でも単位省略不可。
transition-delay: 0s; /* すぐにアニメーション開始 */ transition-delay: 2500ms; /* 2.5秒後にアニメーション開始 */
ちなみに、上記の各プロパティは「transition」でまとめて書くことも可能。
(「border-width」「border-color」と「border」の関係と同様)
秒数は先に書いた方が transition-duration として認識されます。
.move { left: 200px; transition-property: left; /* アニメーションさせるプロパティ名 */ transition-duration: 2s; /* アニメーションにかける時間 */ transition-timing-function: ease-in-out; /* 変化の速度 */ transition-delay: 0s; /* 開始を遅らせる時間 */ } /* 「transition」でまとめて書くことも可能 */ .move { left: 200px; transition: left 2s ease-in-out 0s; }
片側トランジション/両側トランジション
transition をどこに記述するかで、トランジションが「片側だけ」または「両側」に付くかが変わります。
アニメーション後の方に記述(片側トランジション)
/* アニメーション前の状態 */ div { position: relative; left: 0px; width: 75px; height: 75px; background-color: #F00; } /* アニメーション後の状態 */ .move { left: 200px; transition: left 2s ease-in-out 0s; }
アニメーション前の方に記述(両側トランジション)
/* アニメーション前の状態 */ div { position: relative; left: 0px; width: 75px; height: 75px; background-color: #F00; transition: left 2s ease-in-out 0s; } /* アニメーション後の状態 */ .move { left: 200px; }
ベンダープレフィックス
ブラウザに試験実装されているプロパティの名前の頭に付く「-webkit-」「-moz-」などがベンダープレフィックスです。
「transition」は比較的新しく実装されたCSSなので、ブラウザのバージョンによってはベンダープレフィックスが付いていないと機能しません。
各ブラウザのベンダープレフィックスは次のとおり。動かないブラウザを極力減らすなら全部書いておくのが無難です。
.move { -webkit-transition: left 2s ease-in-out 0s; /* Chrome25, Safari6, Android Browser4.3 以前用 */ -moz-transition: left 2s ease-in-out 0s; /* Firefox15 以前用 */ -o-transition: left 2s ease-in-out 0s; /* Opera12 以前用 */ transition: left 2s ease-in-out 0s; }
現在は、ベンダープレフィックスなしでも動くブラウザがほとんどです。iOS 6 以前にも対応したい場合は「-webkit-」を書きましょう。(参考: CSS3 Transitions - Can I use...)
長所・短所
- ハードウェアアクセラレーション(GPU処理)が効くことがあるため
jQuery(JavaScript) で動かすより動きがスムーズになる - 「:hover」等の擬似クラスに使うなら JavaScript は不要
- 旧バージョンブラウザも考慮すると記述が増えて面倒
- jQuery より分かりにくい
animation(CSS)でアニメーション
CSS の「animation」を使ってアニメーションさせます。
アニメーション用に「move」というクラスを作り、そこに「animation」でアニメーションの制御を記述。それを div に(jQueryで)追加することでアニメーションを発動します。
サンプルコード
<button type="button">クリックで移動</button> <div></div>
/* アニメーション前の状態 */ div { position: relative; width: 75px; height: 75px; background-color: #F00; } /* アニメーションの設定 */ .move { animation-name: anime; animation-duration: 2s; animation-timing-function: ease-in-out; animation-delay: 0s; animation-iteration-count: 1; animation-direction: normal; animation-fill-mode: forwards; animation-play-state: running; } /* アニメーションの内容 */ @keyframes anime { 0% { left: 0px; } 100% { left: 200px; } }
$('button').click(function() { $('div').addClass('move'); //divにクラス「move」を追加 });
構造の解説
.move { animation-name: 適用するアニメーション名; animation-duration: アニメーションにかける時間; animation-timing-function: 変化の速度; animation-delay: 開始を遅らせる時間; animation-iteration-count: 繰り返し回数; animation-direction: 繰り返し時の逆再生の有無; animation-fill-mode: 開始前,終了後の状態; animation-play-state: 再生と一時停止の制御; } @keyframes アニメーション名 { 0% { プロパティ名: アニメーション始点の値; } 100% { プロパティ名: アニメーション終点の値; } }
animation-name(適用するアニメーション名)
適用するアニメーション名を指定。
アニメーション名は「@keyframes」の後に続く部分(自由に指定可能)。
animation-name: anime; /* animeという名前のアニメーションを適用 */
animation-duration(アニメーションにかける時間)
アニメーションにかける時間を指定。
秒[s] または ミリ秒[ms] で指定(1秒=1000ミリ秒)。
Firefox では「0秒」でも単位省略不可。
animation-duration: 2s; /* 2秒かけてアニメーション */ animation-duration: 2500ms; /* 2.5秒かけてアニメーション */
animation-timing-function(変化の速度)
アニメーションの変化の速度を指定。
「ease」「ease-in」「ease-out」「ease-in-out」「linear」「step-start」「step-end」の7種。
「steps(ステップ数,startまたはend)」でステップ数分だけ段階的に変化。
「cubic-bezier」で3次ベジェでの数値指定も可能(解説省略)。初期値は ease。
animation-timing-function: ease; /* 加速→減速 */ animation-timing-function: ease-in; /* 加速 */ animation-timing-function: ease-out; /* 減速 */ animation-timing-function: ease-in-out; /* easeよりゆっくり加速→減速 */ animation-timing-function: linear; /* 一定速度 */ animation-timing-function: step-start; /* 即終点 */ animation-timing-function: step-end; /* 終点直前まで始点を維持 */ animation-timing-function: steps(5,start); /* 5段変化(始点で即変化) */ animation-timing-function: steps(5,end); /* 5段変化(始点を維持) */
animation-delay(開始を遅らせる時間)
アニメーションの開始を遅らせる時間を指定。
秒[s] または ミリ秒[ms] で指定(1秒=1000ミリ秒)。初期値は0秒。
Firefox では「0秒」でも単位省略不可。
animation-delay: 0s; /* すぐにアニメーション開始 */ animation-delay: 2500ms; /* 2.5秒後にアニメーション開始 */
animation-iteration-count(繰り返し回数)
アニメーションの繰り返し回数を指定。
小数も指定可能。「infinite」で無限に繰り返し。初期値は1回。
animation-iteration-count: 2; /* 2回繰り返す */ animation-iteration-count: 0.5; /* 半分(50%)アニメーションする */ animation-iteration-count: infinite; /* ずっと繰り返す */
animation-direction(繰り返し時の逆再生の有無)
繰り返し時にアニメーションを逆再生させるかを指定。
「normal」「alternate」「reverse」「alternate-reverse」の4種。
初期値は normal。
animation-direction: normal; /* 始点に戻って繰り返し */ animation-direction: alternate; /* 偶数回は逆再生 */ animation-direction: reverse; /* 毎回逆再生 */ animation-direction: alternate-reverse; /* 奇数回は逆再生 */ /* 旧バージョンのブラウザでは下2つが未対応の場合あり */
animation-fill-mode(開始前,終了後の状態)
アニメーション開始前,終了後の状態を指定。
「none」「forwards」「backwards」「both」の4種。初期値は none。
animation-fill-mode: none; /* 開始前も終了後もアニメーション適用前の状態 */ animation-fill-mode: forwards; /* アニメーション終了後は終点を維持 */ animation-fill-mode: backwards; /* アニメーション開始前は始点を維持 */ animation-fill-mode: both; /* 開始前は始点、終了後は終点を維持 */
@keyframes(アニメーションの名前と内容の指定)
@keyframes の後にアニメーションの名前を記述。
{ } 内にアニメーションのタイミングと内容を指定。
タイミングはアニメーションの始点が「0%」,終点が「100%」で
その瞬間のプロパティ,値でアニメーションの内容を指定。
@keyframes anime { 0% { left: 0px; } /* 始点のアニメーションの内容 */ 30% { left: 50px; } /* 30%経過時のアニメーションの内容 */ 100% { left: 100px; } /* 終点のアニメーションの内容 */ } /* from(0%), to(100%) と書くことも可能 */ @keyframes anime { from { left: 0px; } /* 始点のアニメーションの内容 */ to { left: 100px; } /* 終点のアニメーションの内容 */ }
animation-play-state(再生と一時停止の制御)
アニメーションの再生/一時停止の制御の指定。
「running」「paused」の2種。初期値は running。
擬似クラス や JavaScript で再生制御に用いるのが主(?)。
値を調べることで再生中/一時停止中の判別にも使用可能。
animation-play-state: running; /* 再生 */ animation-play-state: paused; /* 一時停止 */
ちなみに、上記の各プロパティは「animation」でまとめて書くことも可能。
(「border-width」「border-color」と「border」の関係と同様)
ただし、「animation-play-state(再生/一時停止の指定)」は記述不可。
秒数は先に書いた方が animation-duration として認識されます。
.move { animation-name: anime; /* 適用するアニメーション名 */ animation-duration: 2s; /* アニメーションにかける時間 */ animation-timing-function: ease-in-out; /* 変化の速度 */ animation-delay: 0s; /* 開始を遅らせる時間 */ animation-iteration-count: 1; /* 繰り返し回数 */ animation-direction: normal; /* 繰り返し時の逆再生の有無 */ animation-fill-mode: forwards; /* 開始前,終了後の状態 */ } /* 「animation」でまとめて書くことも可能 */ .move { animation: anime 2s ease-in-out 0s 1 normal forwards; }
ベンダープレフィックス
ブラウザに試験実装されているプロパティの名前の頭に付く「-webkit-」「-moz-」などがベンダープレフィックスです。
各ブラウザのベンダープレフィックスは次のとおり。動かないブラウザを極力減らすなら全部書いておくのが無難です。
.move { -webkit-animation: anime 2s ease-in-out 0s 1 normal forwards; /* Chrome, Safari, Android Browser 用 */ -moz-animation: anime 2s ease-in-out 0s 1 normal forwards; /* Firefox15 以前用 */ -o-animation: anime 2s ease-in-out 0s 1 normal forwards; /* Opera12 用*/ animation: anime 2s ease-in-out 0s 1 normal forwards; } /* Chrome, Safari, Android Browser 用 */ @-webkit-keyframes anime { 0% { left: 0px; } 100% { left: 200px; } } /* Firefox15 以前用 */ @-moz-keyframes anime { 0% { left: 0px; } 100% { left: 200px; } } /* Opera12 用*/ @-o-keyframes anime { 0% { left: 0px; } 100% { left: 200px; } } @keyframes anime { 0% { left: 0px; } 100% { left: 200px; } }
現在は、ベンダープレフィックスなしで動くブラウザがほとんどです。iOS 8 以前にも対応したい場合は「-webkit-」を書きましょう。(参考: CSS3 Animation - Can I use...)
長所・短所
- アニメーションとデザインのCSSを切り離して書ける
- 「transition」より複雑なアニメーションを作れる
- 「:hover」等の擬似クラスや常に動くものに使うなら JavaScript は不要
- プロパティが多く記述が長くなりやすい(ややこしい)
- ハードウェアアクセラレーション(GPU処理)が効かない
- 「-webkit-」のベンダープレフィックス必須(2014年9月現在)
transition, animation が動かない時の確認点
transition, animation を使ったアニメーションを作った時に、記述に間違いが無さそうなのに動かないことが何度かありました。
原因を探るのに苦労したので、同じことで困っている人のためにまとめておきます。
「0秒」でも単位は省略できない
transition: left 2s ease 0; /* 動かない */ transition: left 2s ease 0s; /* 動く */
margin, padding などは数値が「0」のとき単位を省略可能。そのせいで transition, animation の秒数指定でも、「0秒」なら単位を省略できると思いがち。
他のブラウザでは単位を省略しても動きます。しかし、Firefox は動きません。
「0秒」であっても必ず単位を付けましょう。
アニメーション前の値は指定が必要
/* 動かない */ div { position: relative; width: 75px; height: 75px; background-color: #F00; } .move { left: 200px; transition: left 2s ease-in-out 0s; } /* 動く */ div { position: relative; left: 0px; width: 75px; height: 75px; background-color: #F00; } .move { left: 200px; transition: left 2s ease-in-out 0s; }
初期値で自動的に値が決まるものは書かなくてもいいだろう。そう思いがちです。
上の例なら、div の left の値は未記入でも「0px」なのは当然。「0px」から transition が実行されそうに思えます。
しかし、大半のブラウザでは動きません。(一部の旧バージョンブラウザでは動きます)
アニメーションに使う値は、必ず「前」と「後」の両方を記述しましょう。
「display」の「none→block」は動かない
/* 動かない */ div { display: none; opacity: 0; } .fade { display: block; opacity: 1; transition: opacity 2s ease-in-out 0s; } /* 動く */ div { height: 0; overflow: hidden; opacity: 0; } .fade { height: auto; opacity: 1; transition: opacity 2s ease-in-out 0s; }
アニメーションの前は「display: none;」で要素を隠しておき、アニメーション開始時に「display: block;」で表示させるという手法は非常に使いたくなります。
しかし、この方法を使うと transition が効きません。
height を「0 → auto」に変化させれば代用に近いことはできます。ただし、height が 0 であっても、「margin」「padding」「border」が空白として残るので前後で書き換えが必要。また、あふれた中身が見えないよう「overflow: hidden;」も必須です。
「display」を使った 表示/非表示 の操作に、CSSアニメーションが対応してくれれば一番楽なんですけどね。
コメント