コンテナーのサイズおよびスタイルクエリーの使用
Baseline2023 *Newly available
Since February 2023, this feature works across the latest devices and browser versions. This feature might not work in older devices or browsers.
* Some parts of this feature may have varying levels of support.
コンテナークエリーを使うと、特定のコンテナー内に含まれている要素に、そのコンテナーの特性に基づいてスタイルを適用することができます。クエリーは、クエリー条件がコンテナーに対して真であるかどうかによって、真または偽を返します。
コンテナークエリーはメディアクエリーと似ています。@media
アットルールは、ビューポートのサイズや端末のその他の特性に基づいて要素にスタイル設定を適用します。同様に、@container
アットルールは、ビューポートではなく、コンテナー要素のサイズやその他のスタイル特性に基づいて要素にスタイルを適用します。コンテナークエリーは、メディアクエリーと同じ構文ルールと論理演算子があります。
@container <container-condition># { /* <スタイルシート> */}
コンテナークエリーには、コンテナーサイズクエリーとコンテナースタイルクエリーの 2 種類があります。
- コンテナーサイズクエリー
サイズクエリーによって、コンテナー要素の現在のサイズに基づいて要素にスタイルを適用することができます。このコンテナー要素は、明示的にサイズクエリーコンテナー として宣言しておく必要があります。
- コンテナースタイルクエリー
スタイル クエリーを使用すると、コンテナー要素のスタイル機能に基づいて要素にスタイルを適用できます。空でない要素がスタイルクエリーコンテナーになることができます。現在、スタイルクエリーが対応しているスタイル特性は、 CSS のカスタムプロパティだけです。この場合、クエリーは、格納する要素のカスタムプロパティの計算値において真か偽を返します。コンテナースタイルクエリーが完全に対応していると、例えば、コンテナーが
display: inline flex
であったり、背景色が非透明である場合など、任意のプロパティ、宣言、計算値に基づいて、要素の子孫にスタイルを適用できるようになります。- コンテナースクロール状態クエリー
スクロール状態クエリーを使用すると、スクロール状態の条件に基づいて、コンテナーの子孫に CSS ルールを選択的に適用することができます。例えば、クエリー対象の要素が部分的にスクロールされているか、コンテナーがスクロールスナップコンテナーに固定されているか、といった条件です。包含要素は、明示的に「スクロール状態クエリーコンテナー」として宣言する必要があります。
このガイドでは、コンテナークエリーの基本的なことを見ていきます。
- コンテナーサイズクエリー
- スコープを制限するための名前付きコンテナー
style()
関数記法を@container
アットルール内の<container-condition>
で使用して、カスタムプロパティによるスタイルクエリーの作成
スクロール状態クエリーは、コンテナースクロール状態クエリーの使用で解説しています。
コンテナーサイズクエリー
コンテナーサイズクエリーは、サイズ条件によって絞り込まれます。コンテナー要素がコンテナーであると宣言され、コンテナー条件がその要素に対して真である場合、関連するスタイル設定がその中にある要素に適用されます。要素のサイズコンテナーは、抑制のある最も近い祖先です。
要素は、container-type
プロパティ(または一括指定のcontainer
)をsize
またはinline-size
に設定することで、「サイズクエリーコンテナー」として宣言されます。
@container (orientation: landscape) { /* このサイズコンテナーの子孫に適用されるスタイル設定 */}.sizeContainer { container-type: size;}
サイズクエリーコンテナーを宣言すると、抑制が追加されます。これはパフォーマンス上必要なことです。DOM 内のすべての要素のサイズを常に問い合わせることは、パフォーマンスと使い勝手に悪影響を及ぼします。さらに、子孫のスタイルがコンテナー要素のサイズを変更した場合、無限ループが発生する可能性があります。
コンテナーサイズクエリーでは、<container-condition>
に 1 つ以上の<size-query>
を記述します。各サイズクエリーはサイズ特性の名前、比較演算子、値を記載します。問い合わせ可能なサイズ特性はwidth
、height
、inline-size
、block-size
、aspect-ratio
、orientation
に制限されています。 1 つ以上の<size-query>
を組み合わせた論理値と構文は、@media
のサイズ特性クエリーと同じです。
form { container-type: inline-size;}@container (10em <= width <= 20em) { /* スタイル */}
この例の<container-condition>
には、単一の<size-query>
—(10em <= width <= 20em)
が記述されています。この場合、すべての<form>
要素は、無名のコンテナークエリーと一致する可能性があります。コンテナークエリー内で宣言されたスタイルは、幅が10em
から30em
までのすべてのフォームの子孫に適用されます。
名前付きコンテナー
<container-condition>
にはオプションで、大文字小文字を区別するcontainer-name
を指定することができます。フォームの例では、<container-condition>
に名前を追加し、container-name
プロパティの値を照合したいフォーム要素の同じ名前に設定することで、クエリーで照合する要素を制限することができます。
container-name
プロパティは、@container
ルールで使用することができるクエリーコンテナー名のリストを指定します。コンテナー名は大文字小文字の区別のある<ident>
値です。コンテナー名を使用することで、コンテナーが直接の親でない場合でも、特定のコンテナーの詳細を問い合わせることができます。
@container [ [ <container-name> ]? <container-query> ]# { /* <スタイルシート> */}
@container
アットルールに名前を追加したら、container-name
プロパティまたはcontainer
の一括指定を使って、コンテナー要素に空白区切りの名前のリストを適用することができます。名前付き@container
アットルールの中に含まれるスタイルは、同じ名前を設定したコンテナーサイズクエリー中で一致する要素にのみ適用されます。
@container card (orientation: landscape) { /* スタイル */}.todo-panel > li { container-type: inline-size; container-name: card;}
この例では、コンテナークエリースタイルブロック内のスタイル設定は、クラスがcards
で、幅が高さより大きい要素の中に入れ子になっているすべての<li>
要素の子孫に適用されます。他にもcontainer-name: card
が適用されている要素でサイズクエリーに一致するものがあれば、それらの要素の子孫にもスタイルが適用されることに注意してください。
@container wide (min-width: 20em) { /* サイズ特性が一致する場合に .sizeContainer の子孫に適用されるスタイル設定 */}@container narrow (max-width: 20em) { /* サイズ特性が一致する場合に .sizeContainer の子孫に適用されるスタイル設定 */}.sizeContainer { container-type: size; container-name: wide narrow;}
この例では、要素はwide
とnarrow
の 2 つのコンテナー名を持っています。class="sizeContainer"
を持つ要素の子孫は、wide
またはnarrow
クエリー(または要素がちょうど 20em の正方形であった場合は両方)のスタイル設定が適用されます。
既定値のcontainer-type: normal
は、コンテナーがサイズコンテナーとなることを防ぎますが、スタイルコンテナーとなることは可能です。 既定値のcontainer-name: none
は、コンテナーが名前を保有していないことを意味しますが、要素が名前のないクエリーに一致することを妨げるものではありません。
コンテナークエリーは、サイズクエリーだけではありません。コンテナーのスタイル特性を問い合わせることもできます。
コンテナースタイルクエリー
コンテナースタイルクエリーは、 1 つ以上のstyle()
関数記法で定義されたコンテナー要素のスタイルを評価する@container
クエリーです。スタイル特性をスタイルクエリーで組み合わせて使用するための論理構文とロジックは、CSS 機能クエリー と同じです。唯一の違いは関数名で、<support-condition>
内ではsupports()
となるのに対して、<style-feature>
内ではstyle()
になります。
@container style(<style-feature>), not style(<style-feature>), style(<style-feature>) and style(<style-feature>), style(<style-feature>) or style(<style-feature>) { /* <スタイルシート> */}
それぞれのstyle()
関数の引数は単一の<style-feature>
です。 CSS コンテナー仕様書によれば、<style-feature>
は有効な CSS宣言、 CSS プロパティ、<custom-property-name>
のいずれかになります。現在対応しているスタイル特性はカスタムプロパティのみで、値の有無は問いません。ブラウザー互換性表を参照してください。
<style-feature>
に値が記載されている場合、style()
引数として渡されたカスタムプロパティ(将来的には CSS 宣言)の計算値が、クエリー対象のコンテナーに対して真であれば、スタイルクエリーは真と評価されます。そうでない場合は、偽に解決されます。値のないスタイル設定は、計算値が指定されたプロパティの初期値と異なる場合に真と評価されます。
将来的には、このようにスタイルクエリーを書くことができるようになるでしょう。
@container style(color: green) and style(background-color: transparent), not style(background-color: red), style(--themeBackground), style(--themeColor: blue) or style(--themeColor: purple), (max-width: 100vw) and style(max-width: 600px) { /* <スタイルシート> */}
style()
関数記法はスタイルクエリーとサイズクエリーを区別するために使用しています。まだ対応していませんが、いずれはmax-width: 100vw
のような通常の CSS 宣言もクエリーできるようになるでしょう。@container (max-width: 100vw)
はサイズクエリーです。container-type
またはcontainer
一括指定による抑制が必要です。このクエリーはコンテナーが 100vw 以下の場合に真を返します。これはスタイルクエリーである@container style(max-width: 100vw)
のクエリーとは異なります。対応している場合、このクエリーはmax-width
の値が100vw
のコンテナーがあれば真を返します。
通常の CSS 宣言やプロパティに対するスタイルクエリーに対応するまでは、値の有無にかかわらず、style()
の引数としてカスタムプロパティを記載する方法のみを制限されます。
@container style(--themeBackground), style(--themeColor: blue) or style(--themeColor: purple) { /* <スタイルシート> */}
すでに言及されていることでありますが、覚えておきたいいくつかの注意点です。
- すべての要素がスタイルクエリーコンテナーになることができます。
container-type
を設定する必要はありません。子孫のスタイルが祖先の計算スタイルに影響を与えない場合、抑制は必要ありません。 <container-condition>
にはスタイル設定とサイズ設定の両方を記載することができます。サイズ特性をクエリーに記載する場合は、コンテナー要素のcontainer-type
にsize
またはinline-size
が設定されていることを確認してください。- ある要素をコンテナーとして考慮させたくない場合は、
container-name
を指定して、その要素を使用しないようにしてください。container-name: none
を設定すると、コンテナーに関連するすべてのクエリー名が除去され、要素がスタイルコンテナーになることを防ぐことはできません。 - この執筆時点(2024 年 2 月)では、コンテナースタイルクエリーは
style()
クエリー内の CSS カスタムプロパティ値でのみ動作します。
これで掘り下げて、さまざまな種類の<style-feature>
を見ていきましょう。
カスタムプロパティによるスタイルクエリー
カスタムプロパティ用のスタイルクエリーでは、親要素のカスタムプロパティ(「CSS 変数」とも呼ばれます)を問い合わせることができます。カスタムプロパティは、通常の CSS プロパティを機能クエリーに記載するのと同じように<style-query>
に記載します。
スタンドアロンのカスタムプロパティクエリー
関数記法style()
の<style-query>
引数には、単なる CSS 変数名、つまり値のないカスタムプロパティを指定することができます。値が指定されていない場合、クエリーは値が@property
アットルール内のinitial-value
記述子の値と同じであれば、偽を返します。スタイルクエリーは真を返し、initial-value
と異なるカスタムプロパティ値を持つすべての要素、またはカスタムプロパティが登録されずに宣言された場合は、任意の値のカスタムプロパティを持つすべての要素に一致します。
未登録のカスタムプロパティ
CSS 変数が CSS カスタムプロパティ値の割り当てによって導入された場合、値のないカスタムプロパティクエリーは常に真を返します。
:root { --theme-color: rebeccapurple;}@container style(--theme-color) { /* <スタイルシート> */}
この例では、コンテナークエリーは--theme-color
プロパティが宣言された要素と、そのすべての子孫要素に一致します。 CSS 変数--theme-color
は:root
で宣言されているので、スタイルクエリーstyle(--theme-color)
はそのDOM ノード内のすべての要素に対して真になります。
登録済みプロパティ
登録済みのカスタムプロパティの動作は異なります。明示的に@property
アットルールで定義された場合、またはCSS.registerProperty()
で JavaScript を介して定義された場合、スタイルクエリーstyle(--theme-color)
は、要素の--theme-color
に対する計算値が、そのカスタムプロパティの元の定義で設定されたinitial-value
と異なる場合にのみ、要素に対して真を返します。
@property --theme-color { initial-value: rebeccapurple; inherited: true;}:root { --theme-color: rebeccapurple;}main { --theme-color: blue;}@container style(--theme-color) { /* <スタイルシート> */}
この例では、:root
要素はカスタムプロパティの値がinitial-value
の値と同じであるため、スタイルクエリーに一致しません。要素(およびその値を継承するすべての要素)のカスタムプロパティの値はrebeccapurple
のままです。初期値と異なる要素、この場合は<main>
とその子孫で変更された値を継承するものだけが一致します。
値によるカスタムプロパティ
スタイルクエリーがカスタムプロパティの値を含む場合、その要素のプロパティの計算値は完全一致でなければならず、カスタムプロパティが@property
アットルール(またはCSS.registerProperty()
メソッド呼び出し)で定義された場合にのみ、syntax
記述子を含む等価な値が一致します。
@container style(--accent-color: blue) { /* <スタイルシート> */}
このコンテナースタイルクエリーは、--accent-color
カスタムプロパティの計算値としてblue
を持つ要素に一致します。
この場合、他にも sRGB のblue
に相当する色の値(16 進コードの#0000ff
など)が一致するのは、次のように--accent-color
プロパティが@property
やCSS.registerProperty()
で色として定義されている場合のみです。
@property --accent-color { syntax: "<color>"; inherits: true; initial-value: #00f;}
この場合、--accent-color
の値をblue
、#00f
、#0000ff
、rgb(0 0 255 / 1)
、rgb(0% 0% 100%)
に設定すると、@container style(--accent-color: blue)
は真を返します。
例
この例では、 4 つのラジオボタンを持つ<fieldset>
があります。 4 つ目のオプションには、独自の色を入力するためのテキスト<input>
が含まれています。
<fieldset> <legend><code>--theme</code> の値を変更</legend> <ol> <li> <input type="radio" name="selection" value="red" /> <label for="red">--theme: red;</label> </li> <li> <input type="radio" name="selection" value="green" /> <label for="green">--theme: green</label> </li> <li> <input type="radio" name="selection" value="blue" /> <label for="blue">--theme: blue</label> </li> <li> <input type="radio" name="selection" value="currentcolor" /> <label for="other">その他</label> <label for="color">色:</label> <input text="checkbox" name="selection" value="currentcolor" /> </li> </ol></fieldset><output>色を変更します</output>
JavaScript はラジオボタンが選択されるたびに、<fieldset>
要素と<output>
要素の祖先である<body>
要素上にある、 CSS 変数--theme
の値を更新します。テキストの<input>
が更新されると、other
ラジオボタンのvalue
は、other
ラジオボタンがチェックされている場合のみ、--theme
を更新します。
const radios = document.querySelectorAll('input[name="selection"]');const body = document.querySelector("body");const other = document.getElementById("other");const color = document.getElementById("color");for (let i = 0; i < radios.length; i++) { radios[i].addEventListener("change", (e) => { body.style.setProperty("--theme", e.target.value); });}color.addEventListener("input", (e) => { other.style.setProperty("value", e.target.value); if (other.checked) { body.style.setProperty("--theme", e.target.value); }});
@property
アットルールを使用して、 CSS 変数--theme
が<color>
値となるように定義し、initial-value
を#00F
に設定することで、どのような構文が使用されているかに関わらず、等価な色が確実に一致します(例えば、#F00
はrgb(255 0 0)
、#ff0000
、red
と等しくなります)。
@property --theme { syntax: "<color>"; inherits: true; initial-value: #f00;}
output { padding: 3px 5px; margin-top: 5px;}
最初のスタイル特性クエリーは、値のないカスタムプロパティです。この形式のクエリーは、カスタムプロパティ値の計算値がそのプロパティのinitial-value
と異なる場合に真を返します。この場合、--theme
の値が、#f00
(red
など)と等価な任意の構文以外の値であるとき、真になります。真の場合、<output>
は 5px の点線の輪郭線が付きます。輪郭線の色は現在の--theme
の値です。既定ではcolor
は灰色です。
@container style(--theme) { output { outline: 5px dotted var(--theme); color: #777; }}
2 つ目と 3 つ目のスタイル設定には、カスタムプロパティの値が記載されています。これらは、コンテナーの--theme
の値が列挙された値と等価な色である場合に、initial-value
と同じ値であっても一致します。最初のクエリーは--theme
の値がred
、blue
、green
と等価な要素に一致します。その場合、color
は--theme
の現在の色の値になります(blue
とgreen
の場合、最初のスタイルクエリーで設定した灰色を上書きします)。
2つ目のスタイルクエリーは、--theme
がred
と等しい場合、<output>
のコンテンツも太字になることを示しています。これはコンテナークエリーが一致することをよりよく示すためです。
@container style(--theme: green) or style(--theme: blue) or style(--theme: red) { output { color: var(--theme); }}@container style(--theme: red) { output { font-weight: bold; }}
テキストボックスに様々な色の値を入力してみてください。 sRGB のred
に相当する値にすると、<output>
はstyle(--theme: red)
に一致して赤になりますが、style(--theme)
はアットルール@property
で定義された--theme
の初期値と同じ値を返すので、輪郭線は除去されます。currentcolor
やhsl(180 100% 50%)
など、赤以外の sRGB の有効な色の値を記載すると、最初のスタイルクエリーが真を返します。これらはinitial-value
とは異なる値です。
syntax: "<color>";
を設定しているため、この CSS 変数には有効な<color>
値しか代入できません。color
プロパティの有効な値のうち<color>
値ではないもの、例えばunset
やinherit
など、このカスタムプロパティでは不正な値であり、無視されます。
unset
またはgibberish
を入力すると、 JavaScript は<body>
のstyle
を--theme: unset
または--theme: gibberish
に更新します。どちらも色ではありません。どちらも不正な色であり、無視されます。これは初期値が継承され、変更されないことを意味しています。style(-theme)
は偽を返し、style(-theme: red)
は真を返します。
メモ:カスタムプロパティを宣言するときは、@property
をsyntax
記述子とともに使用するようにしてください。そうすれば、ブラウザーは正しく計算値を比較することができます。
入れ子のクエリー
コンテナークエリーは、他のコンテナークエリーの中に入れることができます。複数の入れ子になったコンテナークエリーの中で定義したスタイルは、それを囲んでいるコンテナークエリーがすべて真のときに適用されます。
@container style(--theme: red) { output { outline: 1px dotted; } @container style(--theme: purple) { output { outline: 5px dotted; } }}
この場合、<output>
が--theme: purple
の設定されているコンテナーの中に入っていて、そのコンテナーが--theme
の値がred
であるコンテナーの中に入っている場合、<output>
には 5px の点線の境界線が付きます。
スタイルクエリーの CSS 宣言とプロパティ
まだどのブラウザーも対応していませんが、style()
関数記法では、 CSS プロパティとプロパティ値のペアを含む通常の CSS 宣言を指定することができます。
@container style(font-weight: bold) { b, strong { background: yellow; }}
対応している場合、この基本的な例は、親要素が既にbold
である場合、<b>
と<strong>
要素の背景色を黄色にします。
照合は親コンテナーの計算値に対して行われ、親の計算値font-weight
がbold
(bolder
や900
ではありません)であれば一致します。カスタムプロパティのコンテナースタイルクエリーと同様に、既定ではすべての要素がスタイルコンテナーであるため、スタイルコンテナーとして要素を定義する必要はありませんでした。要素にcontainer-name
が設定されていない限り、font-weight: bold
が設定されているか継承されていれば、一致します。
一括指定プロパティと照合するスタイル特性は、計算値が個別指定プロパティのそれぞれで一致すれば真となり、そうでなければ偽となります。例えば、@container style(
は、その一括指定を構成する 12 個の個別指定プロパティ(border
: 2px solid red)border-bottom-style
など)がすべて同じ等価な値に設定されていれば真になります。
グローバル CSS 値revert
とrevert-layer
は<style-feature>
の値としては無効であり、コンテナースタイルクエリーが偽になります。
スタイルクエリーでクエリーしているスタイルを、そのクエリーでスタイル設定している要素に適用しないでください。無限ループを発生させる可能性があります。
スタイルクエリーは、論理値コンテキストのプロパティも受け入れることを想定しています。スタイルクエリーは、プロパティの値がそのプロパティの初期値(変更されていない場合)であれば偽を返し、そうでなければ真を返します。
@container style(font-weight) {}
上記の例は、font-weight
の値が初期値と異なる要素に対して真を返します。ユーザーエージェントのスタイルシートは、例えばfont-weight: bold
を見出しと<th>
要素に対して設定します。ブラウザーによっては<strong>
や<b>
をbold
に設定したり、他にもbolder
に設定したりします。<optgroup>
もユーザーエージェントによって、font-weight
にnormal
以外が設定されることがあります。要素のfont-weight
がユーザーエージェントの既定値でない限り、スタイルクエリーは真を返します。
これらの機能はまだどのブラウザーも対応していません。
仕様書
Specification |
---|
CSS Conditional Rules Module Level 5 # container-rule |
ブラウザーの互換性
関連情報
- Media queries
- CSS
@container
アットルール - CSS
contain
プロパティ - CSS
container
一括指定プロパティ - CSS
container-name
プロパティ - コンテナースクロール状態クエリーの使用
aspect-ratio
を理解する- Getting Started with Style Queries (2022)
- Style queries (una.im, 2022)