1. はじめに
ウェブサイトを効率的にレンダリングするには、ユーザーエージェントがページのどの部分が表示されているか、 どの部分が現在表示されている領域に影響を与える可能性があるか、 そして無視できるものは何かを検出できることが必要です。
あるサブツリーがページの残りとある程度独立しているかを推測するために使用できる様々なヒューリスティックがありますが、 それらは脆弱であり、ページへの些細な変更が意図せずそのヒューリスティックの検査に失敗させ、 レンダリングが遅いコード経路に陥る原因となることがあります。 また、ヒューリスティックでは検出が困難または不可能なため、分離したい多くの対象があります。
これらの問題を緩和し、 サブツリーをページの残りから強力かつ予測可能に分離できるようにするために、 本仕様では要素のサブツリーが独立していることを示すcontainプロパティを定義します。
1.1. 値の定義
本仕様は、CSS のプロパティ定義慣例([CSS2])に従い、値定義構文は[CSS-VALUES-3]から採っています。 本仕様で定義されていない値の型は CSS Values & Units [CSS-VALUES-3] で定義されています。 他の CSS モジュールとの組み合わせにより、これらの値型の定義が拡張されることがあります。
定義内に列挙されたプロパティ固有の値に加えて、 本仕様で定義されたすべてのプロパティはプロパティ値としてCSS-wide keywordsを受け入れます。 可読性のため、これらは明示的に繰り返していません。
2. 強いコンテインメント: contain プロパティ
| Name: | contain |
|---|---|
| Value: | none | strict | content | [ size || layout || paint ] |
| Initial: | none |
| Applies to: | 下記を参照 below |
| Inherited: | no |
| Percentages: | n/a |
| Computed value: | キーワードのnone、または一つ以上の size、layout、paint |
| Canonical order: | 文法に従う |
| Animation type: | アニメーション不可 |
ユーザーエージェントは、非表示メディアを含むすべてのメディア上でこのプロパティをサポートすることが期待されます。
contain プロパティは、著者が要素とその内容が可能な限り文書ツリーの残りから 独立していることを示すことを可能にします。 これにより、ユーザーエージェントは contain を適切に使用した場合に より強力な最適化を利用できるようになり、 著者は些細な変更によりページが遅いコード経路に陥ることを心配する必要がなくなります。
- none
- この値はプロパティが効果を持たないことを示します。 要素は通常通りレンダリングされ、コンテインメント効果は適用されません。
- strict
- この値は size layout paint に計算され、 したがって要素に対してすべての形式のコンテインメントを有効にします。
- content
-
この値は layout paint に計算され、
したがって要素に対して サイズのコンテインメントを除くすべての形式のコンテインメントを有効にします。
注: contain: content は広く適用しても比較的「安全」です; 実際の影響はかなり小さく、ほとんどのコンテンツはその制約に抵触しません。 ただし、サイズのコンテインメント を適用しないため、 要素は依然としてその内容のサイズに応じて応答することができ、これによりレイアウトの無効化が望まれるよりもツリーの上方へ波及することがあります。 可能であれば最大限のコンテインメントを得るために contain: strict を使用してください。
- size
- この値は要素に対して サイズのコンテインメント を有効にします。 これにより、コンテインメントボックス をその子孫を調べることなくレイアウトできることが保証されます。
- layout
- この値は要素に対して レイアウトのコンテインメント を有効にします。 これにより、コンテインメントボックス はレイアウト目的において完全に不透明となり、 外部のものが内部のレイアウトに影響を与えられず、その逆も同様です。
- paint
- この値は要素に対して ペイントのコンテインメント を有効にします。 これにより、コンテインメントボックス の子孫がその境界外に描画されないことが保証され、 要素がオフスクリーンまたは非表示である場合、その子孫も表示されないことが保証されます。
このプロパティは一般にすべての要素(CSS Pseudo-Elements 4
§ 4.1 Generated Content Pseudo-elements: ::before and ::after を含む)に適用されますが、
いくつかの種類のコンテインメントは一部の要素に対して効果がない場合があり、
その詳細は § 3 コンテインメントの種類 に記載されています。
さらに、[SVG2] の場合、
contain プロパティは
CSS
レイアウトボックスを持つsvg
要素にのみ適用されます。
例えば、マイクロポスト型のソーシャルネットワークが次のようなマークアップを持っているとします:
< body >
< aside > ...</ aside >
< section >
< h2 > Messages</ h2 >
< article >
Lol, check out this dog: images.example.com/jsK3jkl
</ article >
< article >
I had a ham sandwich today. #goodtimes
</ article >
< article >
I have political opinions that you need to hear!
</ article >
…
</ section >
</ body >
サイトにはおそらく多数のメッセージが表示されますが、それぞれが独立しており他に影響を与えません。 したがって、各メッセージに contain: content をマークしてユーザーエージェントに伝え、 オフスクリーンのメッセージに対する多くの計算をスキップしてページを最適化できるようにします。 各メッセージのサイズが事前に分かっている場合は、さらに制約を伝えるために contain: strict を適用できます。
さらに、HTML の
html
または
body
要素上の used value が none 以外である場合、
body
要素から初期包含ブロック、ビューポート、または キャンバス背景 へのプロパティの伝播は無効になります。
特に、次の点に影響します:
-
writing-mode、direction、および text-orientation(詳細は CSS Writing Modes 3 § 8 The Principal Writing Mode を参照)
-
overflow およびそのロングハンド(CSS Overflow 3 § 3.3 Overflow Viewport Propagation を参照)
-
background およびそのロングハンド(CSS Backgrounds 3 § 2.11.2 The Canvas Background and the HTML <body> Element を参照)
注: 初期包含ブロック、ビューポート、または キャンバス背景
への、html
要素自体に設定されたプロパティの伝播は影響を受けません。
3. コンテインメントの種類
要素が受けることのできるいくつかの種類のコンテインメントがあり、 子孫がページの残りに及ぼす影響を様々な方法で制限します。コンテインメントはユーザーエージェントによるより強力な最適化を可能にし、 著者が機能的単位でページを構成するのを助けます。これは、ある変更が文書にどの程度広く影響するかを制限するためです。
新しいプロパティや機構を導入する仕様の著者は、 それらがコンテインメントの各種にどのように影響するかを検討し、 ここに記載されていない効果があれば自分の仕様に含める必要があります。
3.1. サイズのコンテインメント
要素に サイズのコンテインメント を与えると、 その principal box は サイズコンテインメントボックス になり、次の効果を持ちます:
-
内在サイズは、要素にコンテンツがないかのように決定され、 sizing as if empty のロジックに従います。
注: これは min-content や max-content キーワードの明示的な呼び出しや、 これらの測定に依存する計算(例えば、サイズを含む要素が配置されるグリッドトラックのサイズ決定や、 fit-content sizing がコンテインメントボックスの親にする影響)に影響します。
-
サイズコンテインメントボックスとそのコンテンツのレイアウトは概念的に2つのフェーズで行われます:
- 内容がないかのようにサイズ決定
-
used な width と height は、通常のボックスのレイアウトを行う場合と同様に決定されますが、
ボックスがコンテンツを持たないものとして扱われます—擬似要素(例:::before、::after、または ::marker を含めても同様です)。
置換要素 は、自然な幅と高さを 0 とし、 自然なアスペクト比を持たないものとして扱われなければなりません。
注: サイズのコンテインメントは 自然なアスペクト比 のみを抑制するため、 aspect-ratio のように直接その 優先アスペクト比 に影響するプロパティは尊重されます。
サイズコンテインメントボックスのすべての CSS プロパティは、通常のレイアウト時と同様に考慮されます。 他の仕様が特定の例外を設ける場合があります。
注: 要素自身の サイズ指定プロパティ が内在サイズを指定している場合でも、 それが必ずしも要素をゼロサイズにするわけではありません: 要素自身に設定されたプロパティは引き続き考慮され、それによって要素が大きくなることがあります。
- 固定化された領域内でのレイアウト
- コンテインメントボックス の内容 (擬似要素を含む)は、現在固定されたサイズの コンテインメントボックス に通常通りレイアウトされなければなりません。
注: サイズのコンテインメント はベースライン整列を抑制しません。 その点については レイアウトのコンテインメント を参照してください。
-
サイズコンテインメントボックス は モノリシック です(参照:CSS Fragmentation 3 § 4.1 Possible Break Points)。
img{ width : 100 px ; aspect-ratio : 1 /1 ; contain : size; } < img src = "https://www.example.com/300x100.jpg" >
もし aspect-ratio プロパティが宣言されていなかった場合、 画像は 100px x 0px になっていたでしょう。これはその 自然なアスペクト比 が抑制され、 自然な高さ が 0 と扱われるためです。
しかし、次のいずれかが真である場合、要素にサイズのコンテインメントを与えても効果はありません:
-
要素が principal box を生成しない場合(例:display: contents や display: none の場合)
-
その inner display type が table の場合
-
その principal box が 内部テーブルボックス の場合
-
その principal box が 内部ルビボックス または 非アトミック な インラインレベル ボックスである場合
注: テーブルの内部ボックス(表題を含まないもの)は除外されます。 これはテーブルレイアウトアルゴリズムがボックスをその内流コンテンツより小さくすることを許さないためです。 セルを空としてサイズ決定してから中のコンテンツをサイズを変えずにレイアウトすることは、実質的に未定義の操作です。 width や height を手動で 0 に設定しても、 コンテンツより小さくすることはできません。 この懸念はテーブルのキャプションには当てはまりません。キャプションは内容と独立した固定サイズを持つことが可能です。
3.1.1. 可能なサイズコンテインメント最適化
この節は規範ではありません。
単体では、サイズコンテインメントは大きな最適化機会を提供しません。 単独での主な利点は、コンテインメントボックスのサイズに基づいてその内容をレイアウトしたいツール("コンテナクエリ" 概念を実装するようなJSライブラリなど)が、 子要素のサイズがコンテインメントボックスのサイズに応答し、それがコンテインメントボックスのサイズの変化を引き起こし、 その結果として子のサイズ決定がさらに変化し、コンテインメントボックスのサイズがさらに変わる、いわゆる「無限ループ」を恐れずに動作できる点です。
しかし、これが レイアウトコンテインメント と組み合わされると、 有効にできる可能性のある最適化には(これらに限定されないが)次のようなものがあります:
-
コンテインメントボックスの子孫のスタイルや内容が変更されたとき、 DOM ツリーのどの部分が「汚染(dirtied)」されて再レイアウトが必要になり得るかの計算を、 コンテインメントボックスで止めることができます。
-
ページをレイアウトする際に、 コンテインメントボックスが画面外または遮蔽されている場合、 その内容のレイアウト(つまり「固定化領域内でのレイアウト」)を遅延させたり、優先度を下げて実行したりできます。
3.2. レイアウトコンテインメント
要素に レイアウトコンテインメント を与えると、 その principal box は レイアウトコンテインメントボックス となり、次の効果を持ちます:
-
レイアウトコンテインメントボックスは、独立したフォーマッティングコンテキストを確立します。
-
もしある フラグメンテーションコンテナ が含まれる フラグメンテーションコンテキスト の少なくとも一つが レイアウトコンテインメント を持つか、 あるいはそのフラグメンテーションコンテキストの少なくとも一つのフラグメンテーションコンテナが レイアウトコンテインメントボックスの子孫であり、 同じフラグメンテーションコンテキストの少なくとも一つの以後のフラグメンテーションコンテナが 同じレイアウトコンテインメントを持つ要素の子孫でない場合、 最初の(フラグメンテーションコンテナであるか、またはフラグメンテーションコンテナの祖先である)最初のレイアウトコンテインメントボックスは 残りの断片化フローを「閉じ込める(trap)」必要があります: 断片化はそのレイアウトコンテインメントの境界を越えて続行してはならず、 最初のレイアウトコンテインメント境界内の最後のフラグメンテーションコンテナは、 そのフラグメンテーションコンテキスト内で最後のフラグメンテーションコンテナであるかのように扱われます。
もしフラグメンテーションコンテキスト内の以後の フラグメンテーションコンテナ が 断片化フローにさらにコンテンツが残っている場合にのみ生成されるなら、それらは生成されません。 もしそれらが生成されることが前提となる場合は、 それらはフラグメンテーションコンテキストの一部として残りますが、 断片化フローからは何も受け取りません。
注: 執筆時点では、この点に影響を受ける安定した仕様はありません。 レイアウトコンテインメントが適用される(がすべてではない)フラグメンテーションコンテナを可能にする仕様が対象です。 これは [CSS-PAGE-3] や [CSS-MULTICOL-1] のケースではありません。 とはいえ、この要件は、(例:[CSS-REGIONS-1]、::nth-fragment() のような仮想的なセレクタなど) いくつかのメカニズムが検討されているため含まれています。レイアウトコンテインメントが意図する保証は、 そのようなメカニズムがこの規則を順守しない限り実現されません。 [CSS-REGIONS-1] には、レイアウトコンテインメントが リージョンに与える影響の詳細があります。
< article > Lorem ipsum…</ article > < div id = a ></ div > < aside > < div id = b ></ div > < div id = c ></ div > </ aside > < aside > < div id = d ></ div > < div id = e ></ div > </ aside > < div id = f ></ div > article{ flow-into : foo;} #a, #b, #c, #d, #e, #f{ flow-from : foo;} aside{ contain : layout} この [CSS-REGIONS-1] の例では、 コンテンツは
#aから#bへ、#bから#cへ流れます。 しかし#cは最初の レイアウトコンテインメントボックス 内の最後のフラグメンテーションコンテナであるため、 残りのコンテンツを閉じ込め、#d、#e、#fには何も流れません。 -
もし overflow プロパティの計算結果が visible または clip(またはその組み合わせ)であれば、 いかなるオーバーフローも インクオーバーフロー として扱われなければなりません。
-
レイアウトコンテインメントボックスは、絶対位置指定の包含ブロックおよび固定位置指定の包含ブロックを確立します。
-
レイアウトコンテインメントボックスは、スタッキングコンテキストを作成します。
-
強制改ページは レイアウトコンテインメントボックス 内で許可されますが、 親への伝播は CSS Fragmentation 3 § 3.1 Breaks Between Boxes に記載されている通常の方法では行われません。
注: これにより、ボックスとその包含要素の間で強制改ページが発生するという、以前は存在しなかった可能性が導入されます(参照:CSS Fragmentation 3 § 4.1 Possible Break Points)。
-
vertical-align プロパティ、またはレイアウトコンテインメントボックスのベースラインの位置を 子孫以外の何かに関連付ける必要のある他のプロパティの目的のために、 コンテインメントボックスはベースラインを持たないものとして扱われます。
ただし、要素に レイアウトコンテインメント を与えても、次のいずれかが真であれば効果はありません:
-
要素が principal box を生成しない場合(例:display: contents または display: none の場合)
-
その principal box が 内部テーブルボックス(ただし table-cell を除く)である場合
-
その principal box が 内部ルビボックス または 非アトミック な インラインレベル ボックスである場合
3.2.1. 可能なレイアウトコンテインメント最適化
この節は規範ではありません。
レイアウトコンテインメント により有効にできる可能性のある最適化には(これらに限定されないが)次のようなものがあります:
-
ページをレイアウトする際に、 別々の コンテインメントボックス の内容を並列にレイアウトできる場合があります。 それらは互いに影響を与えないことが保証されているためです。
-
ページをレイアウトする際に、 コンテインメントボックスが画面外または遮蔽されており、 かつ画面の表示部分のレイアウトがその コンテインメントボックス のサイズに依存しない場合(例えば、コンテインメントボックスがブロックコンテナの終端付近にあり、あなたがブロックコンテナの先頭を見ている場合)、 その コンテインメントボックス の内容のレイアウトを遅延させたり優先度を下げて実行したりできます。
(これを サイズコンテインメント と組み合わせると、 この最適化はより広く適用可能になります。)
3.3. ペイントコンテインメント
要素に ペイントコンテインメント を与えると、 その principal box は ペイントコンテインメントボックス となり、次の効果を持ちます:
-
要素の内容(任意の インク や スクロール可能なオーバーフロー を含む)は、 パディングエッジ の範囲で ペイントコンテインメントボックス にクリップされなければならず、 角のクリッピング を考慮します。 これはクリップされたコンテンツへアクセスしたり存在を示したりするための仕組みの作成を含みません; また、例えば overflow、resize、あるいは text-overflow のような他のプロパティを通じて、 そのような仕組みが作られるのを妨げるものではありません。
注: 本仕様の次のレベル [CSS-CONTAIN-2] はこの効果を オーバーフロクリップエッジ に対して適用するよう精緻化し、 新しい overflow-clip-margin プロパティを考慮します。 overflow-clip-margin をサポートしない実装では、 効果は同一です。
注: この段落で説明される振る舞いは、 overflow-x: visible を overflow-x: clip に、 overflow-y: visible を overflow-y: clip に変更するのと同等であり、 他の overflow-x および overflow-y の値は変更しません。
-
ペイントコンテインメントボックスは、絶対位置指定の包含ブロックおよび固定位置指定の包含ブロックを確立します。
-
ペイントコンテインメントボックスは、スタッキングコンテキストを作成します。
-
ペイントコンテインメントボックスは、独立したフォーマッティングコンテキストを確立します。
ただし、要素に ペイントコンテインメント を与えても、次のいずれかが真であれば効果はありません:
-
要素が principal box を生成しない場合(例:display: contents または display: none の場合)
-
その principal box が 内部テーブルボックス(ただし table-cell を除く)である場合
-
その principal box が 内部ルビボックス または 非アトミック な インラインレベル ボックスである場合
3.3.1. 可能なペイントコンテインメント最適化
この節は規範ではありません。
ペイントコンテインメント により有効にできる可能性のある最適化には(これらに限定されないが)次のようなものがあります:
-
もし コンテインメントボックス が画面外または遮蔽されている場合、 UA は通常その内容の描画をスキップできます。内容もまた画面外/遮蔽されていることが保証されるためです。
注: フィルタの blur() のように、ローカルでない効果を持つ描画効果もあります。 ユーザーエージェントはこれらを追跡する必要があり、子孫が変化したときにそのようなフィルタを持つ要素の一部を再描画する必要が生じる可能性があるため、 たとえ子孫が ペイントコンテインメント を持ち通常ならスキップできる場合でも注意が必要です。
-
クリップされたコンテンツが overflow、resize、 または text-overflow のような別の機構を通じてアクセス可能にされない限り、 UA はボックス分ちょうどの「キャンバス」領域を予約できます。 (類似のスクロール可能な状況、例えば overflow: hidden の場合は、 現在クリップされているコンテンツへスクロールできるため、UA はしばしば予測的にややオーバーペイントしておき、 スクロール直後に表示されるものがあるようにすることがあります。)
-
それらはスタッキングコンテキストであることが保証されるため、 スクロール可能な要素は単一の GPU レイヤーに描画できます。
4. プライバシーに関する考慮事項
本仕様の機能による既知のプライバシー影響はありません。
5. セキュリティに関する考慮事項
本仕様の機能による既知のセキュリティ影響はありません。
他の CSS 仕様と同様に、本仕様は文書のレンダリングに影響を与えますが、 既に他の CSS モジュールを通じて可能であったものや文書のフォーマットに固有のものではない、 誤解を招く形でコンテンツを提示する特別な能力を導入するものではありません。
付録 A. 変更点
本付録は 参考情報 です。
2022年10月25日の勧告からの変更
3件の提案された訂正が正式に規範テキストに組み込まれました:
- 提案訂正 1:
- contain プロパティの計算値の決定方法に小さな調整が行われました: ショートカット値(strict と content)は、 自身に計算される代わりに対応するキーワードに計算されます。 効果は同一であるため、これにより実装がどの構文で達成されたかを正確に保持する必要がなくなります。 また、最短シリアライズの原則により、この重要でない差異はシリアライズを通じて観測不可能になります。
- 提案訂正 2:
- サイズコンテインメントの説明がやや曖昧であったため、実装者が特定のケースで意図された効果について疑問を持つことがありました。 これを意図した動作を変更することなく明確にするため、より正確な説明に置き換えられました。
- 提案修正3:
- CSSワーキンググループは、HTMLの
html要素およびbody要素に対するcontainmentの影響を考慮し忘れていました。特に、レガシーな理由により、いくつかのプロパティがbody要素から外側へ伝播する可能性があることを考慮する必要がありました。追加された本文は、この見落としに対応しています。
実装レポートが複数のエンジンでの実装の詳細を示しています。
以前の変更
本仕様への以前の変更の詳細は、前回の公開の Changes セクションで確認できます。