animation
やtransition
を使ってCSSアニメーションを行った際に、アニメーションがカクついて困った経験はありませんか?そんな時はwill-changeを使うことによって、カクついていたアニメーションをスムーズにすることができます。
この記事ではwill-changeの使う際の実装方法についてご説明します。
will-changeのブラウザサポート状況(2019/3/10時点)
Edge、IE以外の主要なブラウザで利用可能です。
will-changeって何してくれるの?
will-change
を指定することによって、アニメーションのパフォーマンスを上げる事ができます。
アニメーションするプロパティーをwill-changeで指定することによって、ブラウザは事前にアニメーションの準備を行い、その要素がアニメーションを行うのに最適な状態にします。ただし、will-changeを多用すると逆にパフォーマンスの低下を招きます。
will-changeの内部処理については次の記事で詳しく説明しています。
will-changeの基本文法
.target
というクラスを持った要素をアニメーションする場合、will-changeは次のように書きます。
1 2 3 4 | .target{ transition: transform 1s, opacity 1s; will-change: transform, opacity; } |
will-changeプロパティーの使い方
繰り返しになりますが、will-changeを使う場合以下の2点に気をつけてください。
- will-changeはなるべくアニメーションの直前につける。
- 何でもかんでもwill-changeを付けない。
では、アニメーションの直前にwill-changeプロパティーをつける方法を考えてみましょう。大切なことはアニメーションの直前につけて、アニメーション終了後に削除することです。ここで紹介するのはあくまで例ですので、状況に応じて使用してください。
CSSでwill-changeをつける場合
例として.wrapper_area
内の.target
をホバーした際に発火するアニメーションを考えます。
.target
エレメントにマウスが行く前にまず親要素の.wrapper_area
上をマウスが通過するため、次の様に書くと.target
エレメントのホバー前にwill-change
が適用されている状態になります。 1 2 3 4 5 6 7 8 9 10 11 12 | .target{ opacity: 1; transition: opacity 1s: } .wrapper_area:hover .target{ will-change: opacity; } .target:hover{ opacity: .5; } |
1 2 3 4 | *, *:hover { will-change: all; } |
Javascriptでwill-changeをつける
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | let el = document.querySelector('.target'); let wrapper = document.querySelector('.wrapper_area'); // マウスが親要素に入った際にwill-changeを追加 wrapper.addEventListener('mouseenter', addWillChange); // animationが完了した際にwill-changeを削除 // transitionでアニメーションさせる場合はtransitionEndを使用してください。 el.addEventListener('animationEnd', removeWillChange); function addWillChange() { // 取得したい子要素のインデックスを入力 let target = this.children[0]; target.style.willChange = 'opacity'; } function removeWillChange() { this.style.willChange = 'unset'; } |
マウスが親要素に入ったタイミングでwill-changeを付与し、アニメーションが終了した時点でwill-changeを削除しています。
will-changeが使えないブラウザでのハック
Edgeブラウザなどのwill-changeをサポートしていないブラウザでは代わりにtranslateZ
を使用することで同様の効果が得られます。
この3Dのtranslateプロパティーを指定するとレイヤーが新しく生成されます。しかし値自体は0なので画面の表示に影響はありません。
しかしこのプロパティーもwill-changeと同様に多用しないように気をつけてください。
1 | transform: translateZ(0); |
先程のwill-changeを付与するところに追加しておくとwill-changeをサポートしていないブラウザでも対策することができますね。
まとめ
will-changeはうまく使うとカクついたアニメーションをなめらかにすることができます。しかし、『アニメーションの直前に付与する』『多用しない』という2点を守って正しく使わなければ逆にページ全体のパフォーマンスを下げる事があるので注意しましょう。また、EdgeブラウザではtranslateZ(0)
を代わりに使用しましょう。
will-changeを使用していると、ほんとに効いているのか疑問に思うことがあります。
次の記事ではwill-changeの効果の確認方法をご紹介します。