1. はじめに
現代のCSSレンダラーは、ウェブページを素早く効率的に描画するために様々な高度な最適化を行っています。 しかし、これらの最適化は導入時に無視できない初期コストがかかることが多く、 ページの応答性に悪影響を及ぼすことがあります。
しかし、要素を新しいレイヤーに設定することは比較的高価な処理であり、 transformアニメーションの開始が、体感できるほど遅れる原因となることがあります。
この仕様で定義されるwill-changeプロパティを使うことで、 作者は将来的に変更される可能性が高いプロパティを事前に宣言でき、 UAは必要となる前に適切な最適化を行うことができます。 実際に変更が発生したとき、ページは素早く更新されます。
1.1. 値の定義
この仕様はCSSプロパティ定義規約([CSS2])に従い、値定義構文([CSS-VALUES-3])を使用しています。 本仕様で定義されていない値型はCSS Values & Units [CSS-VALUES-3]で定義されています。 他のCSSモジュールとの組み合わせにより、これらの値型の定義が拡張される場合があります。
プロパティ固有の値に加えて、 本仕様で定義されているすべてのプロパティは CSSワイドキーワードも値として受け付けます。 可読性のため、これらは明示的に繰り返していません。
1.2. will-changeの適切な使い方
will-changeプロパティは、 他のパフォーマンスヒントと同様に、 「正しく」使い方を身につけるのが難しい場合があります。 特に、作者が直接その効果を検知できることがほとんどないためです。 しかし、いくつかの簡単な「やるべきこと・やってはいけないこと」があり、 will-changeの使い方を直感的に理解するのに役立ちます。
多くのプロパティや要素にwill-changeを乱用しないこと
will-changeを初めて見た際によくある反応は、次のようなコードが良いアイデアだと思うことです:
* { will-change: transform, opacity /* , ... */; }
すべてを最適化するようにブラウザに指示すれば、 当然良いはずだと思うかもしれません。
違います。ブラウザはすでにできる限り最適化しようとしています。 明示的に指示しても効果はなく、 実際には大きな悪影響を及ぼす場合があります。 will-changeに関連する強力な最適化は マシンのリソースを大量に消費することがあり、 このように乱用するとページが遅くなったりクラッシュすることもあります。
さらに、will-changeにはいくつか副作用があり、 すべての要素にこれらの副作用が必要なケースはほぼありません。
スタイルシート内でwill-changeを慎重に使うこと
スタイルシートでwill-changeを直接使う場合、 対象の要素が常に何らかの変更直前であると暗黙的に示すことになります。 これは通常意図するところではありません。 実際には、will-changeは 変更前後にスクリプトでオン・オフするのが一般的です(変更が止まった要素のリソースを無駄にしないこと参照)。 ただし、will-changeを直接スタイルシートで使うのが適切な場合もあります。
body > .sidebar { will-change: transform; /* ユーザー操作時に'transform'でサイドバーをスライドさせる。 */ }
要素数が少ないため、 最適化の効果がほとんど使われなくても大きな問題にはなりません。
.cats-flying-around-the-screen { will-change: left, top; }
will-changeが効果を発揮する十分な時間を与えること
よくある誤った使い方は、アニメーションやプロパティ変更の直前にwill-changeを要素に適用することです。 残念ながら、多くの最適化は適用に時間がかかるため、 すぐにセットアップできず、will-changeの効果がほとんどありません。 何かが変化することを少し前に予測し、 will-changeをその時点でセットするようにしましょう。
.element { transition: opacity .2s; opacity: 1; } .element:hover { will-change: opacity; } .element:active { opacity: .3; }
ただし、このようなルールはhoverで効果が発生する場合には意味がありません。 このような場合でも、事前にアクションを予測する方法を見つけることが多いです。 例えば、親要素のhoverで十分なリードタイムを与えられる場合があります:
.element { transition: opacity .2s; opacity: 1; } .container:hover > .element { will-change: opacity; } .element:hover { opacity: .3; }
変更が止まった要素のリソースを無駄にしないこと
一部プロパティの変更に使われる最適化は高コストなため、 ブラウザは通常、できるだけ早くそれらを解除して通常動作に戻します。 しかし、will-changeはこの動作を一般的に上書きし、 ブラウザが通常よりも長く最適化を維持します。
そのため、will-changeを特にスクリプトで要素に追加した場合は、 変更が終わった後に忘れずに削除し、 ブラウザが消費しているリソースを回収できるようにしましょう。
2. 将来の挙動のヒント: will-change プロパティ
名前: | will-change |
---|---|
値: | auto | <animateable-feature># |
初期値: | auto |
適用対象: | すべての要素 |
継承: | no |
パーセンテージ: | n/a |
算出値: | 指定値 |
正規順序: | 文法に従う |
アニメーション型: | アニメーション不可 |
<animateable-feature> = scroll-position | contents | <custom-ident>
will-change プロパティは、作者がどのような種類の変更を要素に対して行う予定かをユーザーエージェントに伝えるための描画ヒントです。 これにより、ユーザーエージェントはその変更をスムーズに描画するために必要な最適化を事前に行うことができ、 作者がその機能の変更やアニメーションを開始したときに「ジャンク」を回避できます。
値の意味は以下の通りです:
- auto
- 特別な意図を示しません。 ユーザーエージェントは通常通りのヒューリスティックや最適化を適用すべきです。
- scroll-position
-
作者が近い将来、要素のスクロール位置をアニメーションまたは変更する予定であることを示します。
例えば、 ブラウザはスクロール可能な要素の「スクロールウィンドウ」内のコンテンツや、その先の一部コンテンツのみを描画することがよくあります。 スキップ描画によるメモリや時間の節約と、スクロールの見栄えのバランスを取っています。 この値が指定されている場合、ブラウザはスクロールウィンドウ周辺の描画範囲を広げ、 より長く・速いスクロールをスムーズに行えるようにするかもしれません。
- contents
-
作者が近い将来、要素の内容に関して何らかの変更やアニメーションを行う予定であることを示します。
例えば、ブラウザは要素の描画を時間とともに「キャッシュ」することが多いですが、 ほとんどの要素は頻繁に変更されず、位置だけが変わることが多いです。 しかし、もし要素が絶えず内容を変更する場合は、 このキャッシュを作成・維持するのは無駄になります。 ブラウザはこの値を、該当要素で積極的なキャッシュを控える、またはキャッシュ自体をやめて都度再描画する信号として利用するかもしれません。
この値は主に、JSベースのアニメーションで毎秒多数回内容を変更するケースでブラウザが最適化できるように意図されています。 この種の最適化は、宣言型アニメーションが使われる場合、すでに自動的に行われていることが多いです。
注: この値は、宣言された要素のサブツリー全体にほぼ適用されます。 つまり、ブラウザは子孫すべてが何らかの変更を受けるものと考えます。 文書の上位要素に使うとページのパフォーマンスに大きな悪影響が出ることがあります。 なるべく文書ツリーの「下位」の要素、最小限の範囲にだけ使うようにしてください。
- <custom-ident>
-
<custom-ident> が組み込みCSSプロパティ名と ASCII 大文字小文字無視で一致する場合、
作者は近い将来そのプロパティを要素で変更またはアニメーションする意図を示します。
指定プロパティがショートハンドの場合は、展開されるすべてのロングハンドに関する意図を示します。
例えば、 will-change: background; を指定すると、 will-change: background-image, background-position, ... など背景プロパティが展開されるすべてのプロパティを指定したのと同じ意味になります。
ここで使われる <custom-ident> 生成規則は、 will-change、none、all、 auto、scroll-position、contents など 通常 <custom-ident> から除外されるキーワードも含め除外します。
注: 多くのプロパティは指定しても効果がありません。 なぜなら、ほとんどのプロパティ変更に対して特別な最適化を行うUAは少ないからです。 ただし、指定しても安全です。 単に効果がないだけです。
カスタムプロパティを指定しても効果はありません。 つまり、カスタムプロパティによる効果は 下記の「非初期値で何かが起きる」条件には該当しません。
注: 未知のプロパティ名を指定しても問題ありません。 単に効果がないだけです。 これにより、あるUAにだけ存在する新しいプロパティを安全に指定でき、 それを知らない古いUAに悪影響を与えることはありません。
例えば、 transform に初期値以外を設定した要素は、通常の要素と大きく異なる扱いになります。 例えば、独自の「GPUレイヤー」に描画したり、transformが生み出す変形に素早く対応できる仕組みが使われます。 UAは transform の値を、要素が変形される前に即座にレイヤー昇格させる信号として扱い、 従来レイヤーの再描画による遅延を防ぎます。
プロパティの非初期値が要素でスタッキングコンテキストを作る場合、 will-change でも スタッキングコンテキストを作る必要があります。
プロパティの非初期値が絶対位置要素の包含ブロックを生成する場合、 will-change でも 包含ブロックを生成する必要があります。
プロパティの非初期値が固定位置要素の包含ブロックを生成する場合、 will-change でも 包含ブロックを生成する必要があります。
プロパティの非初期値がレンダリング挙動(例:テキストのアンチエイリアス戦略)を変える場合、 UAは will-change でそのプロパティが指定された時点で その代替レンダリングを使い、後で値が変わった際の描画差異を防ぐべきです。
例えば、 opacity に 1 以外を指定すると要素でスタッキングコンテキストが作られます。 したがって、will-change: opacity を指定すると、現在 opacity が 1 でも スタッキングコンテキストが作られます。
will-change プロパティは、上記で説明したスタッキングコンテキストや包含ブロックの生成以外に、 指定要素自体に直接的な効果はありません。 あくまでUAへの描画ヒントであり、 特定種類の変更に対してコストの高い最適化を事前に行うことを可能にします。
3. セキュリティに関する考慮事項
本書に対するセキュリティ懸念は報告されていません。
4. プライバシーに関する考慮事項
本書に対するプライバシー懸念は報告されていません。
5. 謝辞
元々 will-animate プロパティを提案し、初期設計を多く担った Benoit Girard 氏に感謝します。
6. 変更点
2015年12月3日 CR以降の変更:
-
セキュリティおよびプライバシーセクションの追加
-
未知の値は問題なく、効果がないことを明確化
-
プロパティ名の比較はASCII大文字小文字無視で行うことを明記
-
will-changeプロパティのアニメーション型を「アニメーション不可」に変更
-
propdefテーブルから "Media:" 項目を削除(他のCSS仕様と同様)
-
細かな編集上の明確化、マークアップ改善
2014年4月29日 ワーキングドラフト以降の変更:
-
will-change の使い方ガイダンスを説明するセクションを追加
-
ショートハンドの動作を明記