1. はじめに
これは CSS Containment Level 2との差分仕様です。 現時点では探索的作業草案(Exploratory Working Draft)です。 実装を行う場合は、Level 2を参照してください。 この草案がCRに到達した際に、Level 2の本文をこのドラフトに統合します。
1.1. モジュールの相互作用
この文書は、これまでの仕様には存在しなかった新機能を定義します。 また、安定した際には[CSS-CONTAIN-1]を置き換え、上位仕様とすることを目指しています。
1.2. 値の定義
この仕様は、CSS2のプロパティ定義規約と、CSS-VALUES-3の値定義構文に従っています。 本仕様で定義されていない値型はCSS Values & Units [CSS-VALUES-3]で定義されています。 他のCSSモジュールと組み合わせることで、これらの値型の定義が拡張される場合もあります。
各プロパティ定義に記載されている固有の値に加えて、 本仕様で定義されるすべてのプロパティは CSS全体キーワードも値として受け付けます。 読みやすさのため、ここでは明示的に繰り返し記載していません。
2. 強いコンテインメント:containプロパティ
CSS Containment 2 § 2 強いコンテインメント:containプロパティ
名前: | contain |
---|---|
新しい値: | layout || style || paint || [ size | inline-size ] |
- inline-size
-
この値は要素にインラインサイズ・コンテインメントを有効にします。
これにより、そのprincipal
boxのインラインサイズが直接内容によって決まることを防ぎます。
注:間接的な依存関係は依然として存在し得ます。 詳細は§ 3.1 インラインサイズ・コンテインメントを参照してください。
3. コンテインメントの種類
CSS Containment 2 § 3 コンテインメントの種類
3.1. インラインサイズ・コンテインメント
要素にインラインサイズ・コンテインメントを与えると、そのprincipal boxのインライン軸サイズにサイズ・コンテインメントが適用されます。 つまり、インライン軸の固有サイズは、内容がないものとして算出されます。 ただし、内容は通常通りボックスのブロック軸 固有サイズに影響を与え続け、 ボックスはブロック軸で通常通り分断されます。
例えば、スクロールバーが表示された場合、 その後、結果的にブロックサイズが小さくなってスクロールバーが不要になっても、 スクロールバーは削除されません。 あるいは、ボックスの論理高さが下に配置されたフロートと衝突し、下方にクリアされてインライン方向に空きができて短くなり、 そのため衝突しなくなった場合でも、元の問題のある高さや位置に戻ることはありません。
このように、インラインサイズ・コンテインメントによって、 ボックスの内容がインラインサイズに直接影響を与えることは防がれますが、 インライン軸 固有サイズを通じて間接的に内容に依存することはあり得ます。 ボックスのインラインサイズが、ブロックサイズの影響で間接的に内容に依存し得ます。
一般的に、要素のインラインサイズと ブロックサイズの関係は予測困難かつ単調ではありません。 インラインサイズを変更するとブロックサイズが上下に任意に変化する可能性があります。 無限ループは、レイアウトが以前の(既知の問題のある)状態に戻らないようにすることで防止されます。 つまり、レイアウトは常に「前進」します。 現在のCSSレイアウト仕様にはこのようなルールが含まれていると考えていますが、 もし含まれていない場合は、CSSWGにご連絡ください。 そのような誤りは修正されます。
< section style = "width: 200px; border: solid; display: flow-root;" > < div style = "float: left; width: 50px; height: 80px; background: blue;" ></ div > < div style = "float: right; width: 50px; height: 80px; background: blue;" ></ div > < div style = "float: left; width: 160px; height: 80px; background: navy;" ></ div > < article style = "border: solid orangered; display: flow-root; min-width: min-content" > < div style = "background: orange; aspect-ratio: 1/1;" > Article</ div > </ article > </ section >
ブロックレイアウトアルゴリズムはまず浮動ボックス(float)を配置します。 最初の2つはコンテナの左右の隅に収まり、 3つ目は間に収まらないため下方に押し出されます。
続いてarticle
がレイアウトされます。
display:
flow-rootであるため、
floatと交差せず、
サイズと位置決定の際にfloatを考慮する必要があります。
レイアウトエンジンはまずarticle
をコンテナの上端に配置しようとします。
この時、幅は100pxとなり、
min-contentサイズには十分な広さです。
しかし、子要素のaspect-ratioのため、
article
の高さも100pxとなり、
80px下の3つ目のfloatと衝突するため、
このレイアウトは却下されます。
次に、article
を3つ目のfloatの上端に合わせて、右側の狭い40pxのスペースに配置しようとします。
しかし、article
のmin-widthが
3つ目のfloatの横の40pxスペースに収まらないため、
さらに下にずれて、すべてのfloatの下に200pxの正方形となります。
もしarticle
からmin-widthが削除されるか、
article
またはheader
にinline-size containmentが追加されると
(これによってmin-width: min-contentが0に解決される)、
article
は最終的にフロートされたdiv
の隣に40px四方として収まることになります
(一部の内容がはみ出す可能性もあります)。
この時点で、article
の幅と高さ(40pxずつ)は、
最初に検討されたスペースに戻って収まるはずであり、
コンテナの上部にぴったりと配置されます。
しかし、ボックスは以前の位置に戻されません。
なぜなら、レイアウトエンジンはすでに
この位置では無効なレイアウトになるとわかっているからです。
要素にinline-size containmentを与えても、以下のいずれかが当てはまる場合は効果がありません:
-
要素がprincipal boxを生成しない場合(display: contentsやdisplay: noneの場合など)
-
そのinner display typeがtableの場合
-
そのprincipal boxが internal table boxである場合
-
そのprincipal boxが internal ruby boxや非atomicなinline-levelボックスの場合
4. コンテナクエリ
メディアクエリは、ドキュメントが表示されているユーザーエージェントやデバイス環境の側面 (ビューポートの寸法やユーザーの設定など)を問い合わせる方法を提供しますが、 コンテナクエリは、ドキュメント内の要素の側面 (ボックス寸法や算出スタイルなど)をテストできます。
デフォルトでは、すべての要素はクエリコンテナとして コンテナスタイルクエリが可能です。 コンテナサイズクエリとして クエリコンテナを確立するには、 container-typeプロパティ (またはcontainerのショートハンド)で追加のクエリタイプを指定します。 クエリコンテナの shadow-including descendantsに適用されるスタイルルールは、 @container 条件グループ規則を用いて、 クエリコンテナに対して条件付けできます。
main, aside{ container : my-layout / inline-size; } .media-object{ display : grid; grid-template : 'img' auto'content' auto /100 % ; } @container my-layout( inline-size >45 em ) { .media-object{ grid-template : 'img content' auto / auto1 fr ; } }
メインエリアやサイドバー領域のメディアオブジェクトは、それぞれ自身のコンテナコンテキストに応じて反応します。
疑似要素付きのセレクターの場合、クエリコンテナは shadow-including inclusive ancestorsや ultimate originating elementによって確立できます。
-
疑似要素自体はクエリコンテナにはなれません
-
::before、::after、::marker、::backdropはそれぞれの起点となる要素をクエリします
-
::first-letterや::first-lineは、fictional tag sequenceによって継承や描画の目的で
::first-line
が他の要素を超えて移動される場合でも、起点要素をクエリします -
複数の疑似要素では、他の疑似要素のクエリコンテナにはなれません。例えば、hostが
host::part()::before
で::before
のクエリコンテナになりますが、::part()
はなれません。同様に、::before
はdiv::before::marker
で::marker
のクエリコンテナにはなれません。 -
::slotted()セレクターは、シャドウツリー内のコンテナ(slot自身を含む)をクエリできます
-
::part()セレクターは、起点となるホストをクエリできますが、シャドウツリー内の内部クエリコンテナはクエリできません
-
::placeholderや::file-selector-buttonはinput要素をクエリできますが、input要素がシャドウツリーで実装されている場合は内部コンテナは公開されません
< style > # container { width : 100 px ; container-type : inline - size ; } @ container ( inline-size < 150px ) { # inner :: before { content : "BEFORE" ; } } </ style > < div id = container > < span id = inner ></ span > </ div >
< div id = host style = "width:200px" > < template shadowroot = open > < style > # container { width : 100 px ; container-type : inline - size ; } @ container ( inline-size < 150px ) { :: slotted ( span ) { color : green ; } } </ style > < div id = container > < slot /> </ div > </ template > < span id = slotted > Green</ span > </ div >
4.1. クエリコンテナの作成:container-type プロパティ
名前: | container-type |
---|---|
値: | normal || [ size | inline-size ] |
初期値: | normal |
適用対象: | 全ての要素 |
継承: | しない |
パーセンテージ: | 該当なし |
算出値: | キーワードnormal、またはsize、inline-sizeのいずれか一つ以上 |
正規順序: | 文法に従う |
アニメーション型: | アニメーション不可 |
container-typeプロパティは、その要素を クエリコンテナとして確立します。 これはコンテナクエリ( コンテナサイズクエリなど明示的なコンテインメントが必要なもの)に利用され、 子孫のスタイルルールが、そのサイズやレイアウトの様々な側面を問い合わせて、 それに応じたスタイリングができます。
特に記載がない限り、 すべての要素はクエリコンテナです。 これはコンテナクエリ( コンテナスタイルクエリなど 明示的なコンテインメントを必要としないもの)に対して有効です。 container-typeの指定に関わらず有効です。
値の意味は以下の通りです:
- size
- クエリコンテナとして、 コンテナサイズクエリ(インライン軸と ブロック軸両方)に対応します。 レイアウトコンテインメント、スタイルコンテインメント、 サイズコンテインメントをprincipal boxに適用します。
- inline-size
- クエリコンテナとして、 コンテナサイズクエリ(自身のインライン軸)に対応します。 レイアウトコンテインメント、 スタイルコンテインメント、 インラインサイズコンテインメントをprincipal boxに適用します。
- normal
- この要素はクエリコンテナとして コンテナサイズクエリには対応しませんが、 コンテナスタイルクエリには引き続き対応します。
aside, main{ container-type : inline-size; } h2{ font-size : 1.2 em ; } @container ( width >40 em ) { h2{ font-size : 1.5 em ; } }
クエリ条件で使われている40emの値は、 該当算出値としての font-sizeに相対的です。 これは関連するクエリコンテナに対するものです。
section{ container-type : style; } @container ( --cards: small) { article{ border : thin solid silver; border-radius : 0.5 em ; padding : 1 em ; } }
4.2. クエリコンテナの命名:container-name プロパティ
名前: | container-name |
---|---|
値: | none | <custom-ident>+ |
初期値: | none |
適用対象: | 全ての要素 |
継承: | しない |
パーセンテージ: | 該当なし |
算出値: | キーワードnone、または識別子の順序付きリスト |
正規順序: | 文法に従う |
アニメーション型: | アニメーション不可 |
container-nameプロパティは クエリコンテナ名のリストを指定します。 これらの名前は@container規則で 対象となるクエリコンテナのフィルタに利用できます。
- none
- クエリコンテナには クエリコンテナ名がありません。
- <custom-ident>
- クエリコンテナ名として識別子を指定します。 キーワードnone、and、not、orはこの<custom-ident>には使用できません。
main{ container-type : size; container-name : my-page-layout; } .my-component{ container-type : inline-size; container-name : my-component-library; } @container my-page-layout( block-size >12 em ) { .card{ margin-block : 2 em ; } } @container my-component-library( inline-size >30 em ) { .card{ margin-inline : 2 em ; } }
4.3. 名前付きコンテナの作成:containerショートハンド
名前: | container |
---|---|
値: | <'container-name'> [ / <'container-type'> ]? |
初期値: | 個々のプロパティを参照 |
適用対象: | 個々のプロパティを参照 |
継承: | 個々のプロパティを参照 |
百分率: | 個々のプロパティを参照 |
算出値: | 個々のプロパティを参照 |
アニメーション型: | 個々のプロパティを参照 |
正規順序: | 文法通り |
containerショートハンドプロパティは、 container-typeとcontainer-nameを同じ宣言で設定します。 <'container-type'>が省略された場合、 その値は初期値にリセットされます。
main{ container : my-layout / size; } .grid-item{ container : my-component / inline-size; }
4.4. コンテナクエリ:@container規則
@container規則は、 条件付きグループ規則であり、 その条件はcontainer query(コンテナクエリ)で、 container size queryやcontainer style queryのブール式の組み合わせです。 <stylesheet>ブロック内の宣言は、 その条件でフィルタリングされ、 container queryが要素のquery containerに対して真の場合のみ適用されます。
@container規則の構文は以下の通りです:
@container [ <container-name> ]? <container-condition> { <stylesheet> }
各要素に対して、 クエリ対象となるquery containerは、 その要素の祖先のquery containerの中から、 <container-condition>で使われている container featureすべてに対して有効な query containerとして確立されているものの中から選ばれます。 オプションの<container-name>は、 query containerセットを query container nameが一致するものに絞り込みます。
有効なquery containerが選択されると、 <container-condition>内の各 container featureは そのquery containerに対して評価されます。 祖先に有効なquery containerがない場合、 その要素に対するcontainer queryは unknownとなります。
@container card( inline-size >30 em ) andstyle ( --responsive: true) { /* スタイル */ }
上記のスタイルは、「card」という名前の祖先コンテナが inline-size条件とstyle条件の両方を満たす場合のみ適用されます。
複数ネストされたcontainer query内の要素に対するスタイルルールは、 すべてのラップしているcontainer queryが その要素に対して真の場合のみ適用されます。
注: ネストされたcontainer queryは異なるコンテナに対して評価されることがあるため、 個々の<container-condition>を 一つのクエリに統合することは常に可能とは限りません。
@container card( inline-size >30 em ) { @container style ( --responsive: true) { /* スタイル */ } }
上記のスタイルは、「card」という名前の祖先コンテナが inline-size条件を、 さらに祖先コンテナがstyle条件を満たす場合のみ適用されます。
at-rule(@keyframesや@font-face、@layerなど)のようなグローバルで名前を定義する ルールがcontainer query内で定義された場合、 そのcontainer queryの条件には制約されません。
4.5. アニメーション付きコンテナ
container queryの評価が変化した場合は、 スタイル変更イベントの一部でなければならず、 その変化がアニメーション効果によって発生した場合も同様です。
main{ display : flex; width : 300 px ; } #container{ container-type : inline-size; flex : 1 ; } /* 解決された幅は初期状態で200pxですが、#siblingのトランジション進行によって変化します。 */ #inner{ transition : 1 s background-color; background-color : tomato; } /* このコンテナクエリが適用開始(または終了)すると、#innerのbackground-colorのトランジションが開始する必要があります。 */ @container ( width <=150 px ) { #inner{ background-color : skyblue; } } #sibling{ width : 100 px ; transition : width1 s ; } #sibling:hover{ width : 200 px ; }
< main > < div id = container > < div id = inner > Inner</ div > </ div > < div id = sibling > Sibling</ div > </ main >
算出値がcontainer query length単位によって変化した場合も、 スタイル変更イベントの一部でなければなりません。
5. コンテナ機能
コンテナ機能は、 クエリコンテナの特定の側面を問い合わせます。
5.1. サイズコンテナ機能
コンテナサイズクエリは、 クエリコンテナの principal boxのサイズを問い合わせることができます。 個々のサイズ機能 (<size-feature>) を組み合わせたブール式であり、 それぞれがクエリコンテナの特定の次元的特徴を問い合わせます。 <size-feature>の構文は メディア特徴と同様で、 機能名・比較演算子・値からなります。[mediaqueries-5] サイズ機能を サイズクエリに論理結合する ブール構文・ロジックは CSS機能クエリと同じです。 (@supports参照。[CSS-CONDITIONAL-3])
クエリコンテナが principal boxを持たない場合や、 principal boxがlayout containment boxでない場合、 またはクエリコンテナが該当軸のコンテナサイズクエリをサポートしない場合、 サイズ機能の評価結果は不明となります。
相対長単位 (container query length単位を含む)は コンテナクエリ条件内で 算出値を基準に クエリコンテナで評価されます。
注: これはメディアクエリ内の相対単位の扱いとは異なります。
aside, main{ container-type : inline-size; } aside{ font-size : 16 px ; } main{ font-size : 24 px ; } @container ( width >40 em ) { h2{ font-size : 1.5 em ; } }
クエリ条件で使われる40emの値は、 該当する算出値の font-sizeを基準に クエリコンテナごとに評価されます:
-
aside内のh2では、クエリ条件は640px以上で真になります。
-
main内のh2では、クエリ条件は960px以上で真になります。
5.1.1. 幅:width機能
名前: | width |
---|---|
対象: | @container |
値: | <length> |
型: | 範囲 |
widthコンテナ機能は、 幅を クエリコンテナの content boxに対して問い合わせます。
5.1.2. 高さ:height機能
名前: | height |
---|---|
対象: | @container |
値: | <length> |
型: | 範囲 |
heightコンテナ機能は、 高さを クエリコンテナの content boxに対して問い合わせます。
5.1.3. インラインサイズ:inline-size機能
名前: | inline-size |
---|---|
対象: | @container |
値: | <length> |
型: | 範囲 |
inline-sizeコンテナ機能は、 サイズを クエリコンテナの content boxの インライン軸で問い合わせます。
5.1.4. ブロックサイズ:block-size機能
名前: | block-size |
---|---|
対象: | @container |
値: | <length> |
型: | 範囲 |
block-sizeコンテナ機能は、 サイズを クエリコンテナの content boxの ブロック軸で問い合わせます。
5.1.5. アスペクト比:aspect-ratio機能
名前: | aspect-ratio |
---|---|
対象: | @container |
値: | <ratio> |
型: | 範囲 |
aspect-ratioコンテナ機能は、 widthコンテナ機能の値を heightコンテナ機能の値で割った比率として定義されます。
5.1.6. 向き:orientation機能
名前: | orientation |
---|---|
対象: | @container |
値: | portrait | landscape |
型: | 離散値 |
- portrait
- orientation コンテナ機能は、portraitであり、 height コンテナ機能の値が width コンテナ機能の値以上のときです。
- landscape
- それ以外の場合、orientationはlandscapeです。
5.2. スタイルコンテナ機能
コンテナスタイルクエリは、 算出値をクエリコンテナから問い合わせることができます。 これは、 個々のスタイル特徴 (<style-feature>) の論理結合であり、それぞれがクエリコンテナの単一かつ特定のプロパティを問い合わせます。 <style-feature>の構文は 宣言と同じであり、 指定したプロパティの算出値がクエリコンテナ上で与えられた値と一致すれば真 (値も算出されクエリコンテナに対する)、 プロパティや値が無効・非対応の場合はunknown、 それ以外は偽となります。 スタイル特徴をスタイルクエリに論理結合する構文・論理は CSS機能クエリと同じです。 (@supports参照。[CSS-CONDITIONAL-3])
スタイル特徴が ショートハンドプロパティを問い合わせる場合、 算出値が すべてのロングハンドプロパティで一致すればtrue、 そうでなければfalseとなります。
カスケード依存キーワード(revertやrevert-layerなど)は スタイル特徴の値としては無効であり、 その場合はコンテナスタイルクエリはfalseとなります。
注: 残りの非カスケード依存CSS全般キーワードは 他の値と同様にクエリコンテナに対する算出値として計算されます。
6. コンテナ相対長:cqw、cqh、cqi、cqb、cqmin、cqmax単位
コンテナクエリ長単位は、 クエリコンテナの寸法に対して相対的な長さを指定します。 コンテナクエリ長単位を使用するスタイルシートは、 コンポーネントをあるクエリコンテナから他のコンテナへ容易に移動できます。
コンテナクエリ長単位は以下の通りです:
単位 | 基準 |
---|---|
cqw | クエリコンテナの幅の1% |
cqh | クエリコンテナの高さの1% |
cqi | クエリコンテナのインラインサイズの1% |
cqb | クエリコンテナのブロックサイズの1% |
cqmin | cqiまたはcqbの小さい方の値 |
cqmax | cqiまたはcqbの大きい方の値 |
各要素について、コンテナクエリ長単位は 該当軸(または複数軸)に対するコンテナサイズクエリとして評価されます。 各軸に対するクエリコンテナは、 その軸でコンテナサイズクエリを受け入れる最も近い祖先コンテナです。 該当するクエリコンテナが存在しない場合は、 その軸の小さいビューポートサイズを使用します。
注: 同じ要素に対するcqiとcqb単位は異なるクエリコンテナに対し評価される場合があります。 同様に、cqminとcqmax単位も、 それぞれの寸法が異なるクエリコンテナから算出される場合でも、 大きい方と小さい方の値となります。
子要素は、親で指定された相対値を継承せず、 算出値のみを継承します。
/* フォールバック値はcontainmentに依存しません */ h2{ font-size : 1.2 em ; } @container ( inline-size >=0 px ) { /* inline-sizeコンテナが存在する場合のみ適用される */ h2{ font-size : calc ( 1.2 em +1 cqi ); } }
7. API
7.1.
CSSContainerRule
インターフェイス
CSSContainerRule
インターフェイスは、@container規則を表します。
[Exposed =Window ]interface :
CSSContainerRule CSSConditionRule { };
conditionText
型CSSOMString
(CSSConditionRule上の属性のCSSContainerRule固有定義)CSSConditionRule
親規則上で定義されているconditionText
属性は、取得時に指定された条件を論理的な簡略化を行わずに返さなければなりません。 これにより、返された条件は、本仕様のいかなる準拠実装(将来の拡張を含む本仕様の<general-enclosed>拡張メカニズムを実装するものも含む)でも 指定された条件と同じ結果が評価されます。 つまり、トークンストリームの簡略化(空白を1つにまとめたり、任意の場合に省略するなど)は許容されますが、 論理的な簡略化(不要な括弧の削除や結果に基づく簡略化など)は許容されません。
CSSContainerRule用のCSSOM APIの追加 [Issue #7033]
コンテナクエリには
matchContainer
メソッドが必要です。
これはmatchMedia()
とMediaQueryList
インターフェイスをモデルにしますが、WindowではなくElementに適用されます。
レイアウトサイズの計測時、resizeObserver
に類似しますが、追加のコンテナクエリ構文と機能を提供します。 [Issue #6205]
8. 要素内容の完全抑制:content-visibilityプロパティ
CSS Containment 2 § 4 要素内容の完全抑制:content-visibilityプロパティ
9. プライバシーとセキュリティに関する考慮事項
CSS Containment 2 § 5 プライバシーとセキュリティに関する考慮事項
付録A. 変更点
この付録は参考情報です。
2021年12月21日初公開作業草案以降の変更点
2021年12月21日初公開作業草案以降の主な変更点:
-
container-nameの算出値に重複する識別子を含めることを許可。 (Issue 7181)
-
<'container-name'>をcontainerショートハンドで必須に。 (Issue 7142)
-
ショートハンドプロパティのコンテナスタイルクエリでの扱いを明確化。 (Issue 7095)
-
カスケード依存キーワードはスタイル特徴の値として許可されず、コンテナスタイルクエリをfalseにする。 (Issue 7080)
-
container-typeの初期値をstyleに変更。 (Issue 6393)
-
container-typeからblock-size値を削除。 単軸block-size containmentは現状不可能なため。 (Issue 1031)
-
<string>をcontainer-name構文から削除。 コンテナ名は<custom-ident>でなければならない。 (Issue 6405)
-
<'container-name'>と <'container-type'>の順序をcontainerショートハンドプロパティで逆転し、両方とも任意に。 (Issue 6393)
-
<general-enclosed>構文を<container-condition>で許可。 将来の互換性のため。 (Issue 6396)
-
<size-feature>クエリのsize関数構文を削除。 (Issue 6870)
-
クエリコンテナの選択処理を 必要なcontainer-typeを考慮するように更新し、明示的な型選択構文を削除。 (Issue 6644)
-
ステートクエリ機能を削除(延期されたため)。 (Issue 6402)
-
疑似要素やシャドウDOM周りのコンテナ選択を明確化。 (Issue 5984/Issue 6711)
CSS Containment Level 2 からの変更点
-
コンテナクエリに必要な 用語、プロパティ、単位、at-ruleを定義。
謝辞
この仕様への貢献者として Adam Argyle、 Amelia Bellamy-Royds、 Anders Hartvoll Ruud、 Brian Kardell、 Chris Coyier、 Christopher Kirk-Nielsen、 David Herron、 Elika J. Etemad (fantasai)、 Eric Portis、 Ethan Marcotte、 Geoff Graham、 Gregory Wild-Smith、 Ian Kilpatrick、 Jen Simmons、 Kenneth Rohde Christiansen、 L. David Baron、 Lea Verou、 Martin Auswöger、 Martine Dowden、 Mike Riethmuller、 Morten Stenshorne、 Nicole Sullivan、 Rune Lillesveen、 Scott Jehl、 Scott Kellum、 Stacy Kvernmo、 Theresa O’Connor、 Una Kravets、 他多数の方々のコメントと先行研究に感謝します。