CSS コンテインメント(Chrome 52)

要約

新しい CSS Containment プロパティを使用すると、ブラウザのスタイル、レイアウト、ペイント処理の範囲を制限できます。

CSS Containment前: レイアウトに 59.6 ミリ秒かかります。後: レイアウトに 0.05 ミリ秒かかる

いくつかの値を持ち、構文は次のようになります。

    contain: none | strict | content | [ size || layout || style || paint ]

この機能は Chrome 52 以降と Opera 40 以降で利用できます(Firefox でも公開サポートされています)。ぜひお試しいただき、ご意見をお寄せください。

contain プロパティ

ウェブアプリや複雑なサイトを作成する際、パフォーマンスの面で重要な課題は、スタイル、レイアウト、ペイントの効果を制限することです。多くの場合、DOM の全体が計算処理の「対象範囲内」と見なされます。つまり、ウェブアプリで自己完結型の「ビュー」を試みると、DOM の一部を変更すると他の部分に影響する可能性があるため、対象範囲内と対象範囲外をブラウザに指示する方法がありません。

たとえば、DOM の一部が次のようになっているとします。

    <section class="view">
      Home
    </section>

    <section class="view">
      About
    </section>

    <section class="view">
      Contact
    </section>

1 つのビューに新しい要素を追加すると、スタイル、レイアウト、ペイントがトリガーされます。

    <section class="view">
      Home
    </section>

    <section class="view">
      About
      <div class="newly-added-element">Check me out!</div>
    </section>

    <section class="view">
      Contact
    </section>

ただし、この場合は DOM 全体が実質的にスコープ内に収まっています。つまり、スタイル、レイアウト、ペイントの計算では、要素が変更されたかどうかにかかわらず、すべての要素を考慮する必要があります。DOM が大きいほど、必要な計算量が多くなり、アプリがユーザー入力に反応しなくなる可能性があります。

幸い、最新のブラウザは、スタイル、レイアウト、ペイント作業の範囲を自動的に制限する機能が非常に優れています。つまり、何もしなくても処理速度が向上します。

さらに良いニュースは、スコープの制御をデベロッパーに委ねる新しい CSS プロパティ「Containment」が追加されたことです。

CSS Containment は、contain というキーワードを持つ新しいプロパティで、次の 4 つの値をサポートしています。

  • layout
  • paint
  • size
  • style

これらの値を使用すると、ブラウザが行う必要があるレンダリング作業の量を制限できます。それぞれの値について詳しく見てみましょう。

レイアウト(contain: layout)

レイアウトの制限は、contain: paint と並んで、制限の最大のメリットです。

通常、レイアウトはドキュメント スコープであり、DOM のサイズに比例してスケーリングされます。そのため、要素の left プロパティを変更する場合は、DOM 内のすべての要素をチェックする必要があります。

ここで制限を有効にすると、ドキュメント全体ではなく、要素の数をほんの一握りに減らすことができます。これにより、ブラウザの不要な作業が大幅に減り、パフォーマンスが大幅に向上します。

塗料(塗料を含む)

スコープ ペイントは、制限のもう 1 つの非常に便利なメリットです。ペイントの制限は、基本的に対象の要素をクリップしますが、他にもいくつかの副作用があります。

  • 絶対位置要素と固定位置要素の包含ブロックとして機能します。つまり、子要素は、ドキュメントなどの他の親要素ではなく、contain: paint を持つ要素に基づいて配置されます。
  • スタッキング コンテキストになります。つまり、z-index などが要素に影響し、子は新しいコンテキストに従って積み重ねられます。
  • 新しいフォーマット コンテキストになります。たとえば、ペイントを含むブロックレベルの要素がある場合、その要素は新しい独立したレイアウト環境として扱われます。つまり、要素の外側のレイアウトは、通常、その要素の子要素には影響しません。

サイズ(contain: size)

contain: size は、要素の子要素が親のサイズに影響しないことを意味し、推定または宣言されたディメンションが使用されます。そのため、contain: size を設定したにもかかわらず、要素のサイズを(直接または Flex プロパティを介して)指定しなかった場合、0 ピクセル x 0 ピクセルでレンダリングされます。

サイズの包含は、サイズを決定する際に子要素に依存しないようにするためのベルトと中かっこの手法ですが、それだけではパフォーマンス上のメリットはあまりありません。

スタイル(contain: style)

要素のスタイルを変更したことが、DOM ツリー全体にどのような影響を与えるかを予測するのは困難です。たとえば、CSS カウンタの場合、子要素のカウンタを変更すると、ドキュメント内の他の場所で使用されている同じ名前のカウンタ値に影響する可能性があります。contain: style が設定されている場合、スタイルの変更は、その要素を越えて上位に伝播されません。

contain: style は、Shadow DOM で得られるスコープ設定されたスタイルは提供しません。ここでの制限は、スタイルが宣言されたときではなく、スタイルが変更されたときに考慮されるツリーの部分を制限することのみを目的としています

厳格なコンテンツの制限

また、contain: layout paint などのキーワードを組み合わせて、それらの動作のみを要素に適用することもできます。ただし、contain は次の 2 つの値もサポートしています。

  • contain: strictcontain: size layout paint と同じ意味です。
  • contain: contentcontain: layout paint と同じ意味です。

厳密な制限を使用するのは、要素のサイズをあらかじめわかっている場合(またはそのディメンションを予約する場合)に適しています。ただし、ディメンションなしで厳密な制限を宣言すると、サイズ制限が暗黙的に適用されるため、要素が 0 ピクセル × 0 ピクセルのボックスとしてレンダリングされる可能性があります。

一方、コンテンツの制限では、スコープが大幅に改善されますが、要素のサイズを事前に把握または指定する必要はありません。

2 つのうち、デフォルトで使用すべきなのは contain: content です。contain: content がニーズに対して十分に強力でない場合は、厳格な制限をエスケープ ハッチとして扱う必要があります。

ご利用方法をお知らせください

封じ込めは、ページ内で分離しておきたいものをブラウザに伝える優れた方法です。Chrome 52 以降でこの機能をお試しいただき、ご感想をお聞かせください。