CSS Containment


CSS Containment という仕様の目的は、開発者に Web ページの任意のサブツリーをそれ以外から独立させることでサイトパフォーマンスを向上させることです。もしブラウザがページの一部が独立していることを知っていれば、レンダリング時に最適化し、パフォーマンスを向上させることができます。この仕様は単一の CSS プロパティ contain を定義しています。この文書ではその仕様の基本的な目的を説明しています。

基本例

多くの Web ページでは、互いに独立したいくつかのセクションで構成されています。例えば記事の見出しと内容が並んだ以下のようなマークアップで紹介します。

<h1>My blog</h1>
<article>
  <h2>Heading of a nice article</h2>
  <p>Content here.</p>
</article>
<article>
  <h2>Another heading of another article</h2>
  <p>More content here.</p>
</article>

<article> の CSS には contain プロパティに content という値が設定されています。

article {
  contain: content;
}

<article> は他の article タグとは独立しており、 この時 contain: content はブラウザにそのことを伝えるために設定されています。ブラウザは次にこの情報をコンテンツのレンダリング方法の決定に用います。例えば、表示可能な領域の外側の記事はレンダリングしない場合があります。

<article> に contain プロパティが与えられた場合、新しい要素が追加されると、ブラウザは contain プロパティが設定された要素のサブツリーの外側については再レイアウトや再描画を行う必要がないと判断します。ただし、もし <article> が ( height: auto が設定されている時のように) そのコンテンツによってサイズが変わるようスタイリングされている場合は、ブラウザがサイズの変化に対応する必要があるかもしれません。

contain プロパティについて、各 <article> の要素が独立である例を用いて説明しました。

この content という値は contain: layout paint の省略記法です。ブラウザに対して、内部で行われるレイアウト時にその他の要素と完全に区別するよう伝え、要素に関する全てがその境界の内側で描画されます。どの要素も視覚的にオーバーフローしません。

ある要素のスタイルがその外側に影響しないようにすべきということは、web 開発者側にとってはよく知られており、実際ページを作るときにはそうします。しかし、ブラウザはそういった意図は分かりませんし、記事のスタイルがその中で閉じるように描画されるということは最初から分かりません。このプロパティはそのことをブラウザに伝えるのに有用なのです。これを使うことで、こうした知見に基づいたパフォーマンス最適化を行うことができます。

主な概念と用語

この仕様は contain というプロパティのみを定義しています。このプロパティの値には、封じ込めの種類を指定します。

レイアウトの封じ込め

article {
  contain: layout;
}

レイアウトは通常、ドキュメント全体がスコープになっています。つまり、ドキュメント全体の中からたった1つの要素を動かしただけで、様々なところが動かされたかのように扱われます。contain: layout を使うことで、ブラウザに対して必要な要素のみを伝えることができます。このプロパティを指定した要素の中の全てがその要素によって封じ込められ、その他の要素には影響せず、そしてその包含ブロックは独立したフォーマッティングコンテキストになります。

加えて、以下の点に注意する必要があります。

  • float レイアウトはこのプロパティとは独立して作用します。
  • マージンはレイアウトによる封じ込めの境界によって崩れることはありません。
  • レイアウトの封じ込めは position: absolute/fixed が指定されたブロックの子孫要素の包含ブロックになります。
  • この包含ブロックはスタッキングコンテキストを作ります。なので z-index を使うことができます。

ペイントの封じ込め

article {
  contain: paint;
}

Paint containment essentially clips the box to the padding edge of the principal box. There can be no visible overflow. The same things are true for paint containment as layout containment (see above).

Another advantage is that if the containing box is offscreen, the browser does not need to paint its contained elements — these must also be offscreen as they are contained completely by that box.

サイズの封じ込め

article {
  contain: size;
}

Size containment does not offer much in the way of performance optimizations when used on its own. However, it means that the size of the element's children cannot affect the size of the element itself — its size is computed as if it had no children.

If you turn on contain: size you need to also specify the size of the element you have applied this to. It will end up being zero-sized in most cases, if you don't manually give it a size.

スタイルの封じ込め

article {
  contain: style;
}

Despite the name, style containment does not provide scoped styles such as you would get with the Shadow DOM. The main use case is to prevent situations where a CSS Counter could be changed in an element, which could then affect the rest of the tree. 

Using contain: style would ensure that the counter-increment and counter-set properties created new counters scoped to that subtree only.

Note: style containment is "at-risk" in the spec and may not be supported everywhere (it's not currently supported in Firefox).

特殊な値

There are two special values of contain:

  • content
  • strict

We encountered the first in the example above. Using contain: content turns on layout and paint containment. The specification describes this value as being "reasonably safe to apply widely". It does not apply size containment, so you would not be at risk of a box ending up zero-sized due to a reliance on the size of its children.

To gain as much containment as possible use contain: strict, which behaves the same as contain: size layout paint, or perhaps the following to also add style containment in browsers that support it:

contain: strict;
contain: strict style;

参考リンク

CSS プロパティ

外部リンク