CSSのコンテナクエリ

コンテナクエリとは
親コンテナのサイズやスタイルに基づいてスタイルを定義できるCSSの機能。
コンテナサイズクエリとコンテナスタイルクエリがある。
今回はコンテナサイズクエリの話。
具体的に親コンテナの何のサイズに基づいてスタイルを定義できる?
@container(条件) {...}
の「条件」の部分に使用できる記述子リスト↓
width
height
inline-size
block-size
aspect-ratio
orientation
inline-sizeって?
writing-mode
の値によって、width
またはheight
プロパティに対応する。
-
horizontal-〇〇
の場合→width
に対応 -
vertical-〇〇
の場合→height
に対応
writing-mode
の初期値はhorizontal-tb
であるため、inline-size
の初期対応プロパティはwidth
になる。
inline-size
がwidth
に対応する時、block-size
はheight
に対応する。
反対にinline-size
がheight
に対応する時、block-size
はwidth
に対応する。
使用できる記述子
inline-size
max-inline-size
min-inline-size
block-sizeって?
writing-mode
の値によって、width
またはheight
プロパティに対応する。
-
horizontal-〇〇
の場合→height
に対応 -
vertical-〇〇
の場合→width
に対応
writing-mode
の初期値はhorizontal-tb
であるため、block-size
の初期対応プロパティはheight
になる。
使用できる記述子
block-size
max-block-size
min-block-size
aspect-ratioって?
親コンテナの幅と高さの比(アスペクト比)に基づいてスタイルを定義できる。
比とは「ある数が、もう一方の数のどれだけに当たるかを表した数」のこと。
ある要素の幅800px、高さ400pxの場合、幅と高さの比は「800:400」→「2:1」になる。幅は高さの2倍であり、高さは幅の0.5倍である。
aspect-ratio
の分子はwidth
、分母はheight
である。
「aspect-ratio: width / height
」
スラッシュ( /
)とheight
が省略された場合、height
の規定値は1
である。
使用できる記述子
aspect-ratio
max-aspect-ratio
min-aspect-ratio
コード例
@container hoge (aspect-ratio: 3/2) {
// 3 / 2 = 1.5 親コンテナのアスペクト比が1.5と等しい時
.hogehoge {
//style
}
}
@container hoge (max-aspect-ratio: 3/2) {
// 親コンテナのアスペクト比が1.5以下の時
.hogehoge {
//style
}
}
@container hoge (min-aspect-ratio: 2) {
// 2 / 1 = 2 親コンテナのアスペクト比が2以上の時
.hogehoge {
//style
}
}
orientationって?
親コンテナが縦長または横長に基づいてスタイルを定義する。
使用できる記述子
-
portrait
(縦長。幅より高さの値が大きい。) -
landscape
(横長。高さより幅の値が大きい。)

参考サイト
コンテナクエリ全般
inline-size
block-size
aspect-ratio
orientation

基本的な使い方の手順
<div class="parent">
<div class="child">子要素だよ〜🍓</div>
</div>
1.基準コンテナを決定
基準コンテナのサイズが変更された際に、再描画されることをブラウザに知らせるため。
レスポンシブ対応したい要素の祖先要素にcontainer-type
またはcontainer
プロパティを指定する。指定された要素は、基準コンテナになり「コンテナコンテキスト(container context)」と呼ばれる。
上記index.htmlの場合、class属性parent
を持つdiv
要素に指定する↓
.parent {
container-type:inline-size;
//または、container:parent / inline-size;
}
2.@containerを使って条件を指定
基準コンテナのサイズがどうなったらスタイルを適用するのかの定義する。
例えば、「基準コンテナの幅が500px未満の時」という条件は以下のように書く↓
.parent {
container-type:inline-size;
//またはcontainer:parent / inline-size;
max-width:400px;
}
@container (width < 500px) {
.child {
background-color:red;
}
}

注意点
擬似要素は基準コンテナにできない
::before
や::after
などの擬似要素は@container{...}
内でスタイルを定義することは可能だが、基準コンテナにすることはできない。
🙆OK例
<style>
#container {
width: 100px;
container-type: inline-size;
}
@container (inline-size < 150px) {
#inner::before {
content: "BEFORE";
}
}
</style>
<div id=container>
<span id=inner></span>
</div>
🙅NG例
<style>
#container::before {
display:block;
content:"";
width: 100px;
height:100px;
container-type: inline-size;
}
@container (inline-size < 150px) {
#inner {
background-color:red; /*背景色は赤色にならない*/
}
}
</style>
<div id=container>
<span id=inner></span>
</div>
擬似要素がレスポンシブ対応したい要素の祖先になることがない?
NG.htmlのHTML構造
<div id="container">
#container::before
<span id="inner"></span>
</div>
#container::before
は#inner
と兄弟の関係だから祖先ではないから、基準コンテナにはならない。
親要素以外も基準コンテナにできる
親要素のみ基準コンテナになるわけではなく、レスポンシブ対応したい要素から見て祖先に当たる要素にcontainer-type
を指定するとそこが基準コンテナとなる↓
<style>
.ancestor {
container-type: inline-size;
width: 100px;
}
.parent {
width: 160px;
}
@container (inline-size < 150px) {
.inner::before {
content: "BEFORE";
}
}
</style>
<div class="ancestor">
<div class="parent">
<span class="inner"></span>
</div>
</div>
最も近い祖先要素が基準コンテナとなる
<style>
.container {
container-type: inline-size;
}
.ancestor {
width: 100px;
}
.parent {
width: 160px;
}
@container (inline-size < 150px) {
/*基準コンテナの幅が150px未満の時*/
.inner::before {
content: "BEFORE";
}
}
</style>
<div class="container ancestor">
<div class="container parent">
<span class="inner"></span>
</div>
</div>
上記index.htmlの場合、.inner::before
の content: "BEFORE";
は表示されない。つまり、基準コンテナはclass属性container
とparent
を持つdiv
要素である。
レスポンシブ対応したい要素(今回の場合、class属性inner
を持つspan
要素)の複数の祖先要素にcontainer-type
が指定されている場合、最も近い祖先要素が基準コンテナになっていることが分かる。

container-typeとは?
コンテナクエリで使用されるコンテナの種類を指定する。
コンテナの種類↓
normal
inline-size
size
各種類の解説
container-type:normal;
初期値。コンテナサイズクエリのクエリコンテナではないが、コンテナスタイルクエリのクエリコンテナとして残る。
つまり、コンテナサイズクエリはcontainer-type
プロパティを指定する必要があるが、コンテナスタイルクエリは指定しなくて良い。
コンテナスタイルクエリ↓
container-type:inline-size;
基準コンテナの幅または高さのどちらか一方の変更のみを監視して、@container
の条件に一致したとき、レスポンシブ対応したい要素のスタイルが適用される。
@container
の条件として使える記述子↓
- width
- height
- inline-size
- block-size
aspect-ratio
とorientation
は幅と高さ両方の情報がいるので、inline-size
では使えない。
分かりにくいので具体的なコード例↓
container-type
の値を変えてみると違いが分かる
W3Cによる正確な解説↓
Establishes a query container for container size queries on the container’s own inline axis. Applies layout containment, style containment, and inline-size containment to the principal box.
container-type:size;
基準コンテナの幅と高さ両方の変更を監視して、@container
の条件に一致したときレスポンシブ対応したい要素のスタイルが適用される。
@container
の条件として使える記述子↓
-
container-type:inline-size;
で使える記述子全て aspect-ratio
orientation
コード例↓
W3Cによる正確な解説↓
Establishes a query container for container size queries on both the inline and block axis. Applies layout containment, style containment, and size containment to the principal box.

containerプロパティとは?
container-name
とcontainer-type
を一括で指定できるプロパティ。
スラッシュ( / )で値を区切る。
構文↓
.base-container {
container:container-name / container-type;
}

container-nameとは?
コンテナに名前をつけることができる。
複数のコンテナを使うときに名前をつけて区別することができる。
省略可能。
名前つける時のルール抜粋
- 名前は引用符で囲まない
- スペース区切りで複数の名前を指定できる
名前を引用符で囲まない
🙆OK例→container-name:layou;
🙅♂️NG例→container-name:"layout";
スペース区切りで複数の名前を指定できる
例→container-name:width height;
用途がよく理解できていないので、MDNのサンプルコードを載せる↓
.base-container {
container-type: inline-size;
container-name: meta card;
}
@container meta (max-width: 500px) {
p {
visibility: hidden;
}
}
@container card (max-height: 200px) {
h2 {
font-size: 1.5em;
}
}

コンテナクエリの具体的な使用例