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 プロパティを介して)指定しなかった場合、要素は 0px × 0px でレンダリングされます。

サイズ制限は、サイズ設定に子要素に依存しないようにするための予防措置ですが、それ自体はパフォーマンス上のメリットはあまりありません。

スタイル(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 以降でこの機能をお試しいただき、ご感想をお聞かせください。