Firefoxでkeyframeアニメーションがカクカクしてしまう時の対処法
この記事は最終更新から4年以上が経過しています。情報が古くなっている可能性があります。
こんにちは、しばです。
この間Animate.css & wow.jsを使っていたところ、とあるアニメーションがFirefoxで非常にカクカクとした挙動になることが発覚。
Firefoxはシェア率が低いためいつもスルーしてるんですが(2018/7時点だと6.43%らしい)、今回仕事でFirefoxの表示確認が必要だったので調べてみました。
結論から言えばwow.jsは関係なく、@keyframeの解釈が他のブラウザとFirefoxではちょっと異なることが原因でした。詳細をまとめておきたいと思います。
Contents
Firefoxでのカクカクとした挙動
今回は、Animate.cssでflipというアニメーションを使った時に発生しました。
flipは、本来だと以下のような挙動になります。
※これはgif画像
ところが、Firefoxだとこうなる。
半分回転したところで急に拡大、縮小してまた半分回転という動きになってしまっています。(Windows、Macどちらとも)
これは公式のデモの時点でこうなっていました。
調査
flipのAnimate.cssのコードはこちら。
@keyframes flip {
0% {
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, -360deg);
transform: perspective(400px) rotate3d(0, 1, 0, -360deg);
-webkit-animation-timing-function: ease-out;
animation-timing-function: ease-out
}
40% {
-webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg);
transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg);
-webkit-animation-timing-function: ease-out;
animation-timing-function: ease-out
}
50% {
-webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg);
transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg);
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in
}
80% {
-webkit-transform: perspective(400px) scale3d(0.95, 0.95, 0.95);
transform: perspective(400px) scale3d(0.95, 0.95, 0.95);
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in
}
100% {
-webkit-transform: perspective(400px);
transform: perspective(400px);
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in
}
}
/* @-webkit-keyframes省略 */
※最新版のコードとちょっと違うかもですが対応方法は多分同じ
まず、css3アニメーションがおかしくなる原因を調べてみました。
- Firefoxではanimation-delayに0を指定してると動かない→0sと書こう!
- CSS3アニメーション属性の接頭語に「-moz-」がない→「-moz-」を追加しよう!
- CPUだけで処理してるから遅くなってカクカクする→GPU処理にするためにtranslate3d使おう!
だいたいこんな理由が多いようです。
が、今回はあてはまらず。
アニメーションを見る限り、問題あるのは回転中に奥行き(Z軸)の移動がある箇所なので、奥行きに関係ある「perspective」と「translated3d」が何かしら関わってるのではと予想。
実際にprespectiveを全てコメントアウトすると、カクカクとした動きはなくなりました。
しかしperspectiveの値を調整しても一向に直る気配がない。。
親要素に適用できるperspectiveプロパティを使用すると滑らかになるけど軸が変わってしまう。。
などと苦戦していたのですが、こちらの記事をヒントにさらっと解決できました。
Firefoxはkeyframesで記述している着地地点に最短の動作をするため、他の地点でのプロパティの記述を省略すると、chromeでは滑らかに着地地点に向かって変化するのに対し、Firefoxは直線的に変化してしまうようです。
(こちらの記事ではsafariもカクカクしたようですが、今回はsafariは問題なくFirefoxでのみ事象を確認)
そのため、途中過程もしっかり記述を補強してあげることで無事直りました!
flipの記述の例だと以下でスムーズに動くようになりました。
@keyframes flip {
0% {
-webkit-transform: perspective(400px) translate3d(0, 0, 0) rotate3d(0, 1, 0, -360deg);
transform: perspective(400px) translate3d(0, 0, 0) rotate3d(0, 1, 0, -360deg);
-webkit-animation-timing-function: ease-out;
animation-timing-function: ease-out;
}
40% {
-webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg);
transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg);
-webkit-animation-timing-function: ease-out;
animation-timing-function: ease-out;
}
50% {
-webkit-transform: perspective(400px) translate3d(0, 0, 140px) rotate3d(0, 1, 0, -170deg);
transform: perspective(400px) translate3d(0, 0, 140px) rotate3d(0, 1, 0, -170deg);
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in;
}
60% {
-webkit-transform: perspective(400px) translate3d(0, 0, 120px) rotate3d(0, 1, 0, -150deg);
transform: perspective(400px) translate3d(0, 0, 120px) rotate3d(0, 1, 0, -150deg);
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in;
}
70% {
-webkit-transform: perspective(400px) translate3d(0, 0, 100px) rotate3d(0, 1, 0, -100deg);
transform: perspective(400px) translate3d(0, 0, 100px) rotate3d(0, 1, 0, -100deg);
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in;
}
80% {
-webkit-transform: perspective(400px) translate3d(0, 0, 0) scale3d(0.95, 0.95, 0.95);
transform: perspective(400px) translate3d(0, 0, 0) scale3d(0.95, 0.95, 0.95);
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in;
}
100% {
-webkit-transform: perspective(400px);
transform: perspective(400px);
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in;
}
}
/* @-webkit-keyframes省略 */
※ゴリ押しなので、もしかしたらもっとスマートな記述で済むかもしれない
まとめ
この事象が起きない場合も多いかと思いますが、Firefoxでcssアニメーションがカクカクした動きになってしまう場合は、@keyframeの中継地点に気をつけよう!という話でした。
余談ですが、今回調べる中で結構いろんなサイトでFirefoxがカクカクしてました。やっぱり対応ブラウザから外してるところ多いのかな🤔