CSS @container アットルール
Baseline
広く利用可能
*
この機能は広く実装されており、多くのバージョンの端末やブラウザーで動作します。2023年2月以降、すべてのブラウザーで利用可能です。
* この機能の一部は、対応レベルが異なる場合があります。
@container は CSS のアットルールで、コンテナーコンテキストにスタイルを適用する条件付きグループルールです。
スタイル宣言は条件によってフィルタリングされ、条件が真の場合にコンテナー内の要素に適用されます。
この条件は、クエリーされたコンテナーのサイズ、<style-feature>、スクロール状態のいずれかが変化したときに評価されます。
条件には、container-name、<container-query>、あるいはその両方を指定する必要があります。
container-name プロパティは、クエリーコンテナーの名前のリストを指定します。これらは、@container ルールが対象とするコンテナーを絞り込むために使用されます。container-name の値のみが指定されている場合(名前のみのコンテナークエリー)、その container-name 値が 1 つ以上設定されているコンテナーすべてに、含まれているルールが適用されます。
<container-query> 内のコンテナー特性は、選択されたコンテナーに対して評価されます。
<container-name> が指定されていない場合、<container-query> の機能は、一致する container-type を持つ、最も近い祖先のクエリーコンテナーに対して評価されます。
構文
/* <size-query> 付き */
@container (width > 400px) {
h2 {
font-size: 1.5em;
}
}
/* オプションの <container-name> 付き */
@container tall (height > 30rem) {
p {
line-height: 1.6;
}
}
/* <container-name> のみ(クエリーはオプション) */
@container sidebar {
h2 {
background: blue;
}
}
/* <scroll-state> 付き */
@container scroll-state(scrollable: top) {
.back-to-top-link {
visibility: visible;
}
}
/* アンカークエリー付き */
@container anchored(fallback: bottom) {
.infobox::before {
content: "▲";
bottom: 100%;
top: auto;
}
}
/* <container-name> および <scroll-state> 付き */
@container sticky-heading scroll-state(stuck: top) {
h2 {
background: purple;
color: white;
}
}
/* 単一の条件で複数のクエリー */
@container (width > 400px) and style(--responsive: true) {
h2 {
font-size: 1.5em;
}
}
/* 条件リスト */
@container card (width > 400px), style(--responsive: true), scroll-state(stuck: top) {
h2 {
font-size: 1.5em;
}
}
/* 論理値の style() クエリー */
@container style(--theme: one) or style(--theme: two) {
/* 一致するコンテナーのスタイル */
}
@container style((--theme: one) or (--theme: two)) {
/* 一致するコンテナーのスタイル */
}
@container style(--theme: one) and style(--theme: two) {
/* 一致するコンテナーのスタイル */
}
@container style((--theme: one) and (--theme: two)) {
/* 一致するコンテナーのスタイル */
}
@container not style(--theme: one) {
/* 一致するコンテナーのスタイル */
}
/* 範囲の style() クエリー */
@container style(--number > 4) {
/* 一致するコンテナーのスタイル */
}
値
<container-condition>-
オプションの
<container-name>および<container-query>。 条件がtrueの場合、この<stylesheet>で定義されたスタイルが適用されます。<container-name>省略可-
クエリーの対象となるコンテナーの名前です。
<ident>として指定します。クエリーの結果がtrueとなった場合、宣言したスタイルがコンテナーの子孫要素に適用されます。 <container-query>省略可-
コンテナーのサイズ、
<style-feature>、スクロール状態、適用された position-try の代替のいずれかが変更された際に、クエリーコンテナーに対して評価される一連の特性を指定します。
コンテナークエリー内の論理キーワード
論理キーワードを使用してコンテナー条件を定義することができます。
andは 2 つ以上の条件を結合します。orは 2 つ以上の条件を結合します。notは条件を否定します。コンテナークエリーあたり 1 つの 'not' 条件だけが許されており、andまたはorキーワードと同時に使用することはできません。
@container (width > 400px) and (height > 400px) {
/* <stylesheet> */
}
@container (width > 400px) or (height > 400px) {
/* <stylesheet> */
}
@container not (width < 400px) {
/* <stylesheet> */
}
名前付きコンテナーコンテキスト
コンテナーコンテキストには、 container-name プロパティを使用して名前を付けることができます。
.post {
container-name: sidebar;
container-type: inline-size;
}
このために使用する一括指定構文は container であり、 container: <name> / <type> という形式です。例えばこのようにします。
.post {
container: sidebar / inline-size;
}
コンテナークエリーでは、 container-name プロパティを使用して、クエリーコンテナー名と一致するコンテナー集合にフィルタリングします。
@container sidebar (width > 400px) {
/* <stylesheet> */
}
使用法や名前の制約の詳細は container-name ページで説明しています。
記述子
<container-condition> クエリーには、サイズ、スクロール状態、アンカー付きのコンテナー記述子が入ります。
サイズコンテナー記述子
<container-condition> には、 1 つ以上の論理型のサイズクエリーを含めることができ、それぞれは括弧で囲みます。サイズクエリーには、サイズ記述子、値、および記述子に応じて比較演算子が含まれます。クエリーでは、常にコンテンツボックスを基準として測定します。複数の条件を含める場合の構文は、@media サイズ機能クエリーの場合と同じです。
@container (min-width: 400px) {
/* … */
}
@container (orientation: landscape) and (width > 400px) {
/* … */
}
@container (15em <= block-size <= 30em) {
/* … */
}
aspect-ratio-
コンテナーの
aspect-ratioは、<ratio>値として発生したコンテナーの高さに対する幅として計算されます。 block-size-
コンテナーの
block-sizeを<length>値で表したものです。 height-
コンテナーの高さを
<length>値で表現したものです。 inline-size-
コンテナーの
inline-sizeを<length>値で表したものです。 orientation-
コンテナーの方向で、
landscapeまたはportraitのどちらかです。 width-
コンテナーの幅を
<length>値で表したものです。
スクロール状態コンテナー記述子
スクロール状態コンテナー記述子は、<container-condition> 内で scroll-state() 関数の引数として指定されます。例えば、次のような形になります。
@container scroll-state(scrollable: top) {
/* … */
}
@container scroll-state(scrolled: block-end) {
/* … */
}
@container scroll-state(stuck: inline-end) {
/* … */
}
@container scroll-state(snapped: both) {
/* … */
}
スクロール状態コンテナー記述子に対応しているキーワードには、物理値およびフロー相対値が含まれます。
scrollable-
スクロールバーをドラッグしたり、トラックパッドのジェスチャーを使用したりといった、ユーザーによるスクロールによって、コンテナーを指定した方向にスクロールできるかどうかを問い合わせます。つまり、指定した方向にスクロールできるコンテンツがあふれているかどうかです。有効な
scrollable値には、次のキーワードを含めることができます。none-
このコンテナーがスクロールコンテナーでないか、その他の理由でどの方向にもスクロールできない場合。
top-
このコンテナーが上方向にスクロール可能である場合。
right-
このコンテナーが右方向にスクロール可能である場合。
bottom-
このコンテナーが下方向にスクロール可能である場合。
left-
このコンテナーが左方向にスクロール可能である場合。
x-
このコンテナーが左方向と右方向の一方または両方に水平にスクロール可能である場合。
y-
このコンテナーが上方向と下方向の一方または両方に垂直にスクロール可能である場合。
block-start-
このコンテナーがブロックの先頭方向にスクロール可能である場合。
block-end-
このコンテナーがブロックの末尾方向にスクロール可能である場合。
inline-start-
このコンテナーがインラインの先頭方向にスクロール可能である場合。
inline-end-
このコンテナーがインラインの末尾方向にスクロール可能である場合。
block-
このコンテナーがブロックの先頭方向と末尾方向の一方または両方にスクロール可能である場合。
inline-
このコンテナーがインラインの先頭方向と末尾方向の一方または両方にスクロール可能である場合。
条件を満たすと、
@containerブロック内のルールがスクロールコンテナーの子孫に適用されます。方向に関係なく、コンテナーがスクロール可能かどうかを評価するには、
not演算子とnone値を使用してください。css@container not scroll-state(scrollable: none) { /* … */ } scrolled-
コンテナーが最後に指定された方向にスクロールされたかどうかを調べます。有効な
scrolledの値には、以下のキーワードが含まれます。none-
このコンテナーがスクロールコンテナーでないか、その他の理由でどの方向にもスクロールできない場合。
top-
このコンテナーが最後に上方向にスクロールした場合。
right-
このコンテナーが最後に右方向にスクロールした場合。
bottom-
このコンテナーが最後に下方向にスクロールした場合。
left-
このコンテナーが最後に左方向にスクロールした場合。
x-
このコンテナーが最後に左方向と右方向の一方または両方に水平にスクロールした場合。
y-
このコンテナーが最後に上方向と下方向の一方または両方に垂直にスクロールした場合。
block-start-
このコンテナーが最後にブロックの先頭方向にスクロールした場合。
block-end-
このコンテナーが最後にブロックの末尾方向にスクロールした場合。
inline-start-
このコンテナーが最後にインラインの先頭方向にスクロールした場合。
inline-end-
このコンテナーが最後にインラインの末尾方向にスクロールした場合。
block-
このコンテナーが最後にブロックの先頭方向と末尾方向の一方または両方にスクロールした場合。
inline-
このコンテナーが最後にインラインの先頭方向と末尾方向の一方または両方にスクロールした場合。
条件を満たすと、
@containerブロック内のルールがスクロールコンテナーの子孫に適用されます。方向に関係なく、コンテナーがスクロールしたかどうかを評価するには、
none値をnot演算子で使用してください。css@container not scroll-state(scrolled: none) { /* … */ } snapped-
コンテナーが、指定された軸に沿ってスクロールスナップコンテナーの祖先にスナップされているか、またはスナップされるかどうかを問い合わせます。有効な
snappedの値としては、次のキーワードがあります。none-
コンテナーは、その親スクロールコンテナーのスクロールスナップターゲットではありません。
snapped: noneクエリーを実装している場合、スクロールコンテナーのスナップターゲットであるコンテナーには@containerスタイルは適用されませんが、スナップターゲットではないコンテナーにはスタイルが適用されます。 x-
このコンテナーは、その親スクロールコンテナーの水平スクロールスナップターゲットです。つまり、親コンテナーに対して水平方向にスナップします。
y-
このコンテナーは、その親スクロールコンテナーの垂直スクロールスナップターゲットです。つまり、親コンテナーに対して垂直方向にスナップします。
block-
このコンテナーは、その親スクロールコンテナーのブロック軸のスクロールスナップターゲットです。つまり、親コンテナーに対してブロック方向にスナップします。
inline-
このコンテナーは、その親スクロールコンテナーのインライン軸のスクロールスナップターゲットです。つまり、親コンテナーに対してインライン方向にスナップします。
both-
コンテナーは、その親スクロールコンテナーの水平方向および垂直方向のスクロールスナップターゲットであり、両方向に親にスナップします。コンテナーは、水平軸または垂直軸に沿って親にスナップするだけでは一致しません。両方である必要があります。
none以外のsnappedのスクロール状態のクエリーでコンテナーを評価するには、そのコンテナーは、none以外のscroll-snap-type値を持つスクロールコンテナーを祖先とするコンテナーでなければなりません。snapped: noneクエリーは、スクロールコンテナーの祖先がない場合でも一致します。評価は、スクロールスナップコンテナーで
scrollsnapchangingイベントが発生すると行われます。条件を満たすと、@containerブロック内のルールがコンテナーの子孫に適用されます。方向に関係なく、コンテナーがスナップターゲットであるかどうかを評価するには、
not演算子とともにnone値を使用します。css@container not scroll-state(snapped: none) { /* … */ } stuck-
position値がstickyであるコンテナーが、そのスクロールコンテナーの祖先の端に固定されているかどうかを問い合わせます。有効なstuckの値には、次のキーワードがあります。none-
コンテナーは、そのコンテナーのどの端にも固定されていません。コンテナーに
position: stickyが設定されていなくても、noneクエリーは一致することに注意してください。 top-
コンテナーは、そのコンテナーの上端に固定されています。
right-
コンテナーは、そのコンテナーの右端に固定されています。
bottom-
コンテナーは、そのコンテナーの下端に固定されています。
left-
コンテナーは、そのコンテナーの左端に固定されています。
block-start-
コンテナーは、そのコンテナーのブロック方向の先頭に固定されています。
block-end-
コンテナーは、そのコンテナーのブロック方向の末尾に固定されています。
inline-start-
コンテナーは、そのコンテナーのインライン方向の先頭に固定されています。
inline-end-
コンテナーは、そのコンテナーのインライン方向の末尾に固定されています。
none以外のstuckスクロール状態クエリーでコンテナーを評価するには、そのコンテナーにposition: stickyが設定されており、スクロールコンテナー内にある必要があります。条件が成立すると、@containerブロック内のルールがposition: stickyコンテナーの子孫に適用されます。隣接する軸の 2 つの値が同時に一致する可能性があります。
css@container scroll-state((stuck: top) and (stuck: left)) { /* … */ }ただし、反対側の端の 2 つの値は、同時に一致することはありません。
css@container scroll-state((stuck: left) and (stuck: right)) { /* … */ }方向に関係なく、コンテナーがスタックしているかどうかを評価するには、
none値をnot演算子とともに使用します。css@container not scroll-state(stuck: none) { /* … */ }
アンカー付きコンテナー記述子
アンカー付きコンテナ記述子は、<container-condition> 内で anchored() 関数の引数として指定します。例えば、次のような形になります。
@container anchored(fallback: top) {
/* … */
}
@container anchored(fallback: flip-block flip-inline) {
/* … */
}
@container anchored(fallback: --custom-fallback) {
/* … */
}
fallback-
特定の position-try の代替が、現在
position-try-fallbacksプロパティで指定されたアンカー位置指定コンテナーに対して、現在有効かどうかを照会します。有効なfallbackの代替値には、position-try-fallbacksプロパティの値として記載することができるすべての要素値が含まれます。検査で指定された
fallback値が、アンカー位置指定されたコンテナーで現在有効である場合、検査は成功し、@containerブロック内のルールが、そのアンカー位置指定されたコンテナーの子孫要素に適用されます。
公式定義
@container =
@container <container-condition># { <rule-list> }
<container-condition> =
[ <container-name>? <container-query>? ]!
<container-name> =
<custom-ident>
<container-query> =
not <query-in-parens> |
<query-in-parens> [ [ and <query-in-parens> ]* | [ or <query-in-parens> ]* ]
<query-in-parens> =
( <container-query> ) |
( <size-feature> ) |
style( <style-query> ) |
scroll-state( <scroll-state-query> ) |
<general-enclosed>
<style-query> =
not <style-in-parens> |
<style-in-parens> [ [ and <style-in-parens> ]* | [ or <style-in-parens> ]* ] |
<style-feature>
<scroll-state-query> =
not <scroll-state-in-parens> |
<scroll-state-in-parens> [ [ and <scroll-state-in-parens> ]* | [ or <scroll-state-in-parens> ]* ] |
<scroll-state-feature>
<general-enclosed> =
[ <function-token> <any-value>? ) ] |
[ ( <any-value>? ) ]
<style-in-parens> =
( <style-query> ) |
( <style-feature> ) |
<general-enclosed>
<style-feature> =
<style-feature-plain> |
<style-feature-boolean> |
<style-range>
<scroll-state-in-parens> =
( <scroll-state-query> ) |
( <scroll-state-feature> ) |
<general-enclosed>
<style-feature-plain> =
<style-feature-name> : <style-feature-value>
<style-feature-boolean> =
<style-feature-name>
<style-range> =
<style-range-value> <mf-comparison> <style-range-value> |
<style-range-value> <mf-lt> <style-range-value> <mf-lt> <style-range-value> |
<style-range-value> <mf-gt> <style-range-value> <mf-gt> <style-range-value>
<style-range-value> =
<custom-property-name> |
<style-feature-value>
<mf-comparison> =
<mf-lt> |
<mf-gt> |
<mf-eq>
<mf-lt> =
'<' '='?
<mf-gt> =
'>' '='?
<mf-eq> =
'='
例
>コンテナーの大きさに基づいたスタイルの設定
タイトルとテキストを持つカード部品の次の例を考えてみましょう。
<div class="post">
<div class="card">
<h2>カードのタイトル</h2>
<p>カードのコンテンツ</p>
</div>
</div>
コンテナーコンテキストは container-type プロパティを使用して作成することができます。この用途では .post クラスの inline-size 値を使用します。
そして、 @container アットルールを使用することで、 .card クラスの要素に、 650px より狭いコンテナー内でスタイルを適用することができます。
/* インラインサイズに基づくコンテナーコンテキスト */
.post {
container-type: inline-size;
}
/* コンテナーが 650px よりも狭かった場合にスタイルを適用 */
@container (width < 650px) {
.card {
width: 50%;
background-color: lightgray;
font-size: 1em;
}
}
名前付きコンテナーコンテキストの作成
タイトルとテキストを持つカード部品である次の HTML 例があったとします。
<div class="post">
<div class="card">
<h2>カードのタイトル</h2>
<p>カードのコンテンツ</p>
</div>
</div>
まず、 container-type および container-name プロパティを用いてコンテナーコンテキストを作成します。
この宣言の一括指定構文は container ページで説明しています。
.post {
container-type: inline-size;
container-name: summary;
}
次に、コンテナークエリーに名前を追加して、そのコンテナーを対象とします。
@container summary (width >= 400px) {
.card {
font-size: 1.5em;
}
}
入れ子のコンテナークエリー
単一のコンテナークエリーで複数のコンテナーを対象とすることはできません。 同じ効果を持つコンテナークエリーを入れ子にすることは可能です。
以下は、 summary という名前のコンテナーが 400px よりも幅が広く、かつ祖先に 800px よりも幅の広いコンテナーがある場合に、宣言されたスタイルを適用するクエリーです。
@container summary (width > 400px) {
@container (width > 800px) {
/* <stylesheet> */
}
}
コンテナースタイルクエリー
コンテナークエリーは、対象のコンテナー要素のスタイルを計算して評価することもできます。コンテナースタイルクエリーは、1 つ以上の style() 関数記法を使用する @container クエリーです。 論理値の構文と、スタイル機能をスタイルクエリーに結合するロジックは、CSS 機能クエリー と同じです。
@container style(<style-feature>),
not style(<style-feature>),
style(<style-feature>) and style(<style-feature>),
style(<style-feature>) or style(<style-feature>) {
/* <stylesheet> */
}
それぞれの style() の引数は、単一の <style-feature> です。<style-feature> は、有効な CSS 宣言である有効なCSS 宣言(プレーン形式)、単独の CSS プロパティまたは <custom-property-name>(論理値形式)、あるいは範囲比較(範囲形式)のいずれかです。
@container style(--themeBackground),
not style(background-color: red),
style(color: green) and style(background-color: transparent),
style(--themeColor: blue) or style(--themeColor: purple) {
/* <stylesheet> */
}
値のないスタイル特性は、指定されたプロパティの初期値と計算値が異なる場合、真と評価されます。
style() 関数の引数として渡した <style-feature> が宣言である場合、スタイルクエリーは、宣言の値がクエリー対象のコンテナーのそのプロパティの計算値と同じであれば真と評価されます。 そうでない場合は、偽と評価されます。
以下のコンテナークエリーは、コンテナー要素の --accent-color の計算値が blue かどうかを調べます。
@container style(--accent-color: blue) {
/* <stylesheet> */
}
メモ:
カスタムプロパティが blue という値を持つ場合、そのプロパティが @property で色として定義されていない限り、同等の 16 進コード #0000ff は一致しません。
個別指定プロパティを照会するスタイルの機能クエリーは、計算された値が各プロパティで一致する場合は真となり、一致しない場合は偽となります。例えば、 @container style(border: 2px solid red) は、その短縮形を構成する 12 個の個別指定プロパティ(border-bottom-style など)がすべて真であれば真になります。
なお、!importantはスタイルクエリ-内で使用できますが、無視されます。
/* !important は有効だが、効果がない */
@container style(--themeColor: purple !important) {
/* <スタイルシート> */
}
グローバルな revert と revert-layer は <style-feature> の値としては不正なため、コンテナースタイルクエリーは偽になります。
範囲構文
上で説明した単純な <style-feature-name>: <value> 方法に加え、<style-feature> は、=、<、<=、>、または >= を使用した範囲比較として記述することもできます。範囲構文を使用すると、style(--columns >= 3) や style(--gap = 1rem) など、単純な形式では不可能な数値比較をすることができる。これは、両側の解決値を数値的に比較するものだ。
範囲を評価するために、ブラウザーは次の処理を行います。
- 両辺を評価します(カスタムプロパティ名については、
var()とともに使用された場合と同様に検索されます)。 - それぞれの辺を
<number>、<percentage>、<length>、<angle>、<time>、<frequency>、<resolution>のいずれかとして構文解析します。いずれかの側がこれらの型のいずれかとして構文解析できない場合、または両辺の型が一致しない場合、クエリーは偽となります。 - それぞれの辺を計算し(
calc()式がある場合はそれを評価し)、数値比較を行います。
つまり、キーワードのような値を比較する際には範囲構文を使用できません。style(--theme = dark) は、dark が数値型ではないため、常に偽となります。そのような場合は、通常の構文(例えば style(--theme: dark))を使用してください。
範囲の両辺には、カスタムプロパティ名、var() 参照、リテラル値、calc() 式のいずれかを、順序を問わず指定できます。
@container style(3 = --n) {
/* … */
}
@container style(var(--n) = 3) {
/* … */
}
@container style(calc(6/2) = var(--n)) {
/* … */
}
範囲は、3 つの値の形を取ることもでき、この場合、両方の比較演算子が同じ方向を指し、値が区間内に含まれるかどうかを検査します。
@container style(0 < --n < 10) {
/* --n が 0 より大きく 10 未満の場合に真 */
}
@container style(100px > --width > 50px) {
/* --width が 100px 未満で 50px より大きい場合に真 */
}
言い換えれば、style(0 < --n < 10) は style(0 < --n) and style(--n < 10) と同等です。中間値は、左から右へと連鎖的に検査されるのではなく、両方の境界値に対して個別に検査されます。
メモ:
プレーン構文と範囲構文は、見た目は似ていても動作が異なります。--n: calc(6/2) が指定された場合、クエリー style(--n: 3) は偽となります。これは、プレーン形式ではプロパティの計算値 (calc(6/2)) が 3 と直接比較されるためです。これと同等の範囲クエリー style(--n = 3) は真となります。これは、範囲形式では比較を行う前に両側の値を数値的に計算するためです。詳細については、コンテナー内スタイルクエリーガイドのスタイルクエリーにおけるプレーン構文と範囲構文の比較を参照してください。
スクロール状態クエリー
スクロール状態クエリーの例の手順を追って説明については、コンテナースクロール状態クエリーの使用をご覧ください。
仕様書
| 仕様書 |
|---|
| CSS Conditional Rules Module Level 5> # container-type> |
| CSS Anchor Positioning Module Level 2> # container-rule-anchored> |