KDE.BLOG

web制作で学んだことを記していきます

CSS3 transitionのまとめ

個人的に使うことがとても多いCSS3のtransition。
細かい設定をするとなると忘れてしまっている事柄もあるので整理してまとめておきます。

<目次>

transitionができること

変更前と変更後の間の状態をアニメーションで結んでくれます。
例えばこちらのMDNのデモでは、マウスオーバーすると背景色と文字色が反転しますがその変化をtransitionを用いて滑らかに見せています。

transitionが適応できるcssプロパティ

基本的に数値で指定するプロパティは適応できます。
詳細はCSS animatable propertiesを参照。

対応ブラウザ

IEは10以上、それ以外のモダンブラウザでは基本的に問題なく使用できます。
ベンダープレフィックスに関してはandoroidだと4.3までは-webkit-が必要になります。
案件の要件に合わせて-webkit-を付けるか否か判断すればよいでしょう。

そのほか細かい問題として、IE11だとSVGのfillプロパティに対して、IE(10と11)だとbackground-sizeプロパティに対して、transitionが効かない等の問題があります。

詳しくはCan I useをご確認ください。

各プロパティの概要・構文

transition-property

トランジションを適応(アニメーション)させたいプロパティを指定する。

selector1 {
  transition-property: all; /* 初期値。トランジションが適応できる全てのプロパティでアニメーションさせる */
}
selector2 {
  transition-property: none; /* どのプロパティもアニメーションしない */
}
selector3 {
  transition-property: color, opacity[, <propertyName>[,...]]; /* 複数指定の場合はカンマで区切る */
}

transition-duration

トランジションが完了するまでの時間。
単位はs(秒)、もしくはms(ミリ秒)。

selector1 {
  transition-duration: 0s; /* 初期値。実質アニメーションさせない意味なのでほぼ使わない */
}
selector2 {
  transition-duration: .3s300ms); /* 0.3秒(300ミリ秒)アニメーションさせる */
}
selector3 {
  transition-duration: .2s, 1s[, <time>[,...]]; /* 複数指定の場合はカンマで区切る。transition-propertyの値の数によって適応され方が異なる */
}

transition-timing-function

3次ベジェ曲線を指定します。
基本的にはイージングと考えれば良いと思います。

プロパティ値 動き方
ease 初期値
linear 等速
ease-in 開始がゆっくり
ease-out 終了がゆっくり
ease-in-out 開始と終了がゆっくり
step-start 開始時に終了時点へ
step-end 終了時に終了時点へ
steps(<number>,start) <number>段階で変化。開始時に1段階目実行
steps(<number>,end) <number>段階で変化。終了時に<number>段階目実行
cubic-bezier(.69,-0.33,.34,1.27) 任意のベジェ曲線を指定
selector1 {
  transition-timing-function: ease; /* 初期値 */
}
selector2 {
  transition-timing-function: ease, linear[, <function-name>[,...]]; /* 複数指定の場合はカンマで区切る。transition-propertyの値の数によって適応され方が異なる */
}

分かりやすいようにデモを作成してあります。

codepen.io

stepsの考え方に関しては、下記の図が分かりやすいです。
f:id:jinseirestart:20161111181849p:plain https://www.w3.org/TR/css3-transitions/#transition-timing-function-propertyより引用

また任意のイージングを作ることができるcubic-bezier(...)は動きにこだわりたい時に重宝します。
数値を直接打ち込んで動きを作成するのはとても大変なので、下記のようなwebツールを利用すると良いでしょう。

具体的な使い方としては、Easing Function 早見表を見てざっくりとした動きの目安を決めて、その数値をcubic-bezier.comで微調整するのがおすすめです。

transition-delay

トランジション実行までの遅延時間。
単位はtransition-durationと同じs(秒)もしくはms(ミリ秒)。

selector1 {
  transition-delay: 0s; /* 初期値。遅延することなく即実行されます。 */
}
selector2 {
  transition-delay: 1s, 2s[, <time>[,...]]; /* 複数指定の場合はカンマで区切る。transition-propertyの値の数によって適応され方が異なる */
}

このプロパティは使い方次第では非常に強力なアニメーション効果をもたらします。
こちらもわかりやすいようにデモを作成しました。

codepen.io

demo1から順に少しずつ複雑になっていますが、transition-delayを使えば簡単に実装できます。

demo1ではtransition-propertyheightwidthを指定し、widthだけ.5sトランジションの実行を遅らせています。

demo2では各<li>要素に対して.2sずつトランジションの実行を遅らせています。
こういった見せ方の場合は、JavaScriptのループ処理でtransition-delayを指定すると修正が楽です(sassのfor文でもできますが、要素の数を指定しないとならないのが難点)。

demo3もdemo2と同じことをしています。
transition-durationの時間との組み合わせで4辺のラインが一筆書きのようにつながって見えるようにしているのですが、この辺りはtransitionの話とは少し違うので、後日別の形でまとめたいと思います。

transition

上記4つのプロパティをまとめて指定できるため最もよく使うショートハンドプロパティです。
これまでのデモでは便宜上、transition-propertyとか細かく設定していましたが、実際はtransitionプロパティだけで事足りることが多いです。

使用する上で最低限必要となるのはtranstion-durationの値で、値を省略したプロパティは、各々の初期値が適応されます。

selector1 {
  transition: none; /* アニメーションさせない。transition-prperty: none;と同じ意味 */
}
selector2 {
  transition: 1s;
  /* 下記と同じ意味
  transtion-property: all;
  transition-duration: 1s;
  transition-timing-function: ease;
  transition-delay: 0s;
*/
selector3 {
  transition: width 1s linear,
           height .5s ease-in 1s[,...]; /* 複数指定の場合はカンマで区切る。(改行すると分かりやすい) */
  /* 下記と同じ意味
  transtion-property: width, height;
  transition-duration: 1s, .5s;
  transition-timing-function: linear, ease-in;
  transition-delay: 0s, 1s;
*/
}

こちらも簡単なデモを作成してあります。

codepen.io

transitionは指定値の順番が重要で、最初に指定した時間の値はtransition-durationの値として解釈され、2番目の時間の値はtransition-delayの値として解釈されます。

プロパティ値の数による注意

transition-propertyの値の数が、他のtransitionプロパティの値と異なる場合、数の大小によって異なる適応され方になります。
基本的には、よしなにうまいこと処理しようとしてくれます。

selector1 {
  transition-property: color, height, width, opacity;
  transition-duration: 2s, 4s;
  /* 下記と同じ意味(繰り返し) 
  transition-property: color, height, width, opacity;
  transition-duration: 2s, 4s, 2s, 4s;
  */
}
selector2 {
  transition-property: width, opacity;
  transition-duration: 2s,3s,4s,5s;
  /* 下記と同じ意味 (切り捨て)
  transition-property: width, opacity;
  transition-duration: 2s, 4s;
  */

}

transitionendイベント

transitionはアニメーションが完了した時点でtransitionendイベントが発生します。
このイベントを利用することでコールバック関数の実行が可能になります。

var elm = document.querySelector('.selector1');

elm.addEventListener('transitionend', callback, false);

// コールバック関数の定義
function callback(event) {
  ...
}

注意すべき点として、transitionが適応されるプロパティの数だけイベントが発生します。
1回だけイベントを実行させたい場合は、発生するイベントオブジェクトのプロパティを利用する必要があります。

こちらもデモを作成しました。

codepen.io

widthheightの2つのプロパティに対してtransitionendイベントが発生するため、demo1では2回コールバック関数が実行されています。
demo2ではheightに対してのtransitionendイベントのみコールバック関数が実行されています。

クロスブラウザの問題に関して、以前はoTransitionEnd mozTransitionEnd webkitTransitionEnd transitionendと記述することが多かったですが、今ではtranstionendのみでよいでしょう。
もしくはやや古いandroidを心配するのであればwebkitTransitionEndも記述しておくと良いと思われます。

使いどころはwill-change?

正直今までtransitionendイベントは使う場面がありませんでした。
今回transitionendイベントの使いどころを考えたところ、will-changeプロパティの解除に使えそうだと思い、こちらもデモを作成しました。

codepen.io

下記はChromeの開発者ツールでレンダリングの状態を見ながら試してみた結果です。 f:id:jinseirestart:20161116005203g:plain

各ボタンをマウスダウンしたときにwill-change: transform;にして、transitionendwill-change: auto;にしています。
GPUレイヤー(オレンジ色の線)がon/offされているのが確認できたので狙い通りの形にはできました。

まとめ

複数のプロパティに対してtransitionを使用する場合は、値の並び順、数に注意です。

transitionは手軽ながら使い方次第では複雑なアニメーションの実装が可能です。
transitionに非対応のブラウザの場合は、アニメーションはしませんが、変化後の状態は見せられますのでフォールバック(代替)をそこまで対応することなく使えるのが魅力だと感じています。

参考記事