CSS コンテナクエリ(@container)の基本的な使い方

2023年2月に主要ブラウザに対応したコンテナクエリ(CSS container queries)の基本的な使い方についての覚書です。

作成日:2024年4月9日

コンテナクエリとは

コンテナクエリとは、親要素や祖先要素に基づいてスタイルを定義できる CSS の新しい機能です。

以下は MDN の「コンテナーのサイズおよびスタイルクエリーの使用」からの抜粋です。

コンテナクエリはメディアクエリと似ています。

@media アットルールは、ビューポートのサイズや端末のその他の特性に基づいて要素にスタイル設定を適用します。

同様に、 @container アットルールは、ビューポートではなく、コンテナ要素のサイズやその他のスタイル特性に基づいて要素にスタイルを適用します。

コンテナクエリにはコンテナサイズクエリとコンテナスタイルクエリの2種類があります。

  • コンテナ サイズ クエリ
    コンテナ要素の現在のサイズに基づいて要素にスタイルを適用するコンテナクエリ
  • コンテナ スタイル クエリ
    コンテナ要素のスタイル機能に基づいて要素にスタイルを適用するコンテナクエリ。※ 現時点ではブラウザのサポートは限定的です(以下では扱っていません)

例えば、以下の HTML がある場合、コンテナクエリを使って ul 要素のスタイルをその親要素の幅に応じて簡単に切り替えることができます。

<div class="list-wrapper">
  <ul>
    <li>HTML</li>
    <li>CSS</li>
    <li>JavaScript</li>
    <li>TypeScript</li>
    <li>PHP</li>
  </ul>
</div>

ul 要素の親要素の幅に応じてスタイルを適用させるので、.list-wrapper を基準となるコンテナ要素とします。それには .list-wrapper に container-type プロパティを設定します。

.list-wrapper の幅に応じてスタイルを適用するので container-typeinline-size を指定します。

/* 基準となるコンテナに container-type を設定(コンテナコンテキストを宣言) */
.list-wrapper {
  /* インライン方向のサイズ(幅)を対象とする */
  container-type: inline-size;
}

これにより、ブラウザは .list-wrapper がコンテナ要素であることと、その幅(inline-size)を対象としていることを認識してくれます。

そして、@container ルールでコンテナクエリを定義します。

以下ではサイズ特性 width と比較演算子を使って幅が 500px 以上というクエリとそれにマッチした場合に適用するスタイルを設定しています。

@container (width >= 500px) {
  ul {
    display: flex;
    gap: 10px;
    list-style-type: none;
    padding: 0;
  }
}

これで、.list-wrapper の幅が500px以上の場合、その子孫の ul 要素に上記のスタイルが適用されます。

以下は上記コードの動作確認サンプルです。

ブラウザの幅を変更して .list-wrappe の幅が変化すると、.list-wrapper の幅が500pxでリストのスタイルが切り替わります。

  • HTML
  • CSS
  • JavaScript
  • TypeScript
  • PHP

@container (width >= 500px) は @container (min-width: 500px)と同じことです(比較演算子)。

サポート状況

現時点(2024/04)では MDN のドキュメントで Baseline 2023 NEWLY AVAILABLE となっていて、「2023年2月以降、この機能は最新のデバイスとブラウザーのバージョンで動作します。 この機能は、古いデバイスやブラウザでは動作しない可能性があります」とあります。

各ブラウザのサポート状況の詳細は以下で確認できます。

https://caniuse.com/?search=container

以下は コンテナスタイルクエリ(CSS Container Style Queries)のサポート状況です。

https://caniuse.com/css-container-queries-style

参考情報

コンテナクエリのドキュメントやプロパティ、仕様については以下で確認できます。

基本的な使い方

コンテナクエリの使い方をまとめると以下のようになります。

  1. 基準となるコンテナ要素を決める

    基準となるコンテナ要素は、スタイルを適用する要素の親要素や祖先要素になります。

    基準となる適当な要素がない場合は作成します。

  2. 基準となるコンテナ要素でコンテナコンテキストを宣言

    基準となるコンテナ要素に container-type プロパティで、対象とするサイズの種類を指定します。

    基準となるコンテナ要素の横幅(インライン方向のサイズ)に応じてスタイルを適用する場合は、container-type に inline-size を指定します。

    オプショナルで container-name プロパティを使って名前を付けることができます。

    また、container プロパティを使うと container-type と container-name を一括指定できます。

    container-type や container を設定することを「コンテナコンテキストを宣言する」と言います。また、それらが設定された要素は「コンテナコンテキストを持つ」などと言います。

  3. @container ルールでコンテナクエリを定義

    @container ルールを使って条件と、条件にマッチした場合に適用するスタイルを設定します。

例えば、以下の HTML で .foo-wrapper のサイズに基づいて .foo やその子要素にスタイルを適用する場合、基準となるコンテナ要素は .foo-wrapper になります。

<div class="foo-wrapper">
  <div class="foo">
    <h3>foo</h3>
    <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. </p>
  </div>
</div>

基準となるコンテナ要素に container-type プロパティを設定して、コンテナコンテキスト(その要素が基準となるコンテナであることとどのサイズを対象とするか)を宣言します。

/* 基準となるコンテナ要素に container-type を設定(コンテナコンテキストを宣言)  */
.foo-wrapper {
  /* インライン方向のサイズ(幅)を基準とする */
  container-type: inline-size;
}

これでブラウザは .foo-wrapper の幅(inline-size)の変更に反応するようになります。

例えば、.foo-wrapper の幅が 400px 以上の場合に .foo に背景色を設定するには以下のように @container を使ってコンテナクエリを記述します。

/* .foo-wrapper の幅が 400px 以上であれば .foo に背景色を設定 */
@container (width >= 400px) {
  .foo {
    background-color: #c7d4f9;
  }
}

デバッグ(確認)用に resize プロパティを追加

開発段階で、基準となるコンテナ要素をリサイズ可能にしておくとコンテナクエリの動作を確認するのに便利です。

要素をリサイズ可能にするには、resize プロパティにその方向(水平方向の場合は horizontal)と、overflow プロパティに visible 以外を指定します。

.foo-wrapper {
  container-type: inline-size;
  /* 水平方向のリサイズを許可(水平・垂直方向にリサイズ可能するには both を指定) */
  resize: horizontal;
  /* overflow に visible 以外を指定 */
  overflow: auto;
}

@container (width >= 400px) {
  .foo {
    background-color: #c7d4f9;
  }
}

以下は、上記のように.foo-wrapper に確認用の resize プロパティを追加して、初期値として幅 200px を設定したサンプルです。

foo

Lorem ipsum, dolor sit amet consectetur adipisicing elit.

※ resize プロパティは iPhone などではサポートされていません。

https://caniuse.com/css-resize

特定の要素の親要素をコンテナにする

:has() を使って、*:has(> セレクタ) のように特定のセレクタの直接の親要素を基準となるコンテナ要素とすることができます。

但し、この場合、意図しない要素が基準となるコンテナ要素になる可能性もあるので注意が必要です。

<div class="sample">
  <div class="foo">
    <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. </p>
  </div>
</div>
*:has(> .foo) {
  /* .foo の親要素を全てコンテナとする  */
  container-type: inline-size;
}

@container (width >=400px) {
  .foo {
    background-color: #f9c7ee;
  }
}

Lorem ipsum, dolor sit amet consectetur adipisicing elit.

基準となるコンテナ要素

基準となるコンテナ要素自身にはコンテナクエリを指定できません。

コンテナクエリで基準となるコンテナ要素自身 にスタイルを指定しても機能しません(無効です)。

.foo-wrapper {
  container-type: inline-size;
}

@container (width >= 400px) {
  /* 基準となるコンテナ要素自身を指定しても機能しない(無効) */
  .foo-wrapper {
    background-color: red;
  }
}

但し、基準となるコンテナ要素の擬似要素(::before など)にスタイルを指定することはできます。

.foo-wrapper {
  container-type: inline-size;
}

/* 基準となるコンテナ要素の擬似要素 */
.foo-wrapper::before {
  content: 'before';
}

@container (width >= 400px) {
  /* 基準となるコンテナ要素の擬似要素を指定することは可能(有効) */
  .foo-wrapper::before  {
    background-color: red;
  }
}

プロパティ

container-type

container-type では、基準となるコンテナ要素の対象とするサイズ(コンテナコンテキスト)を指定します。以下を指定することができます。

container-type プロパティの値
説明
inline-size インライン方向のサイズ(横幅)を対象とする
size インライン方向及びブロック方向のサイズを対象とする。※ size を指定する場合、基準となるコンテナ要素に height を指定する必要あります。
normal コンテナサイズクエリーの基準となるコンテナ要素ではない(初期値)。

基準となるコンテナ要素の横幅に基づいてスタイルを適用する場合は、inline-size を指定します。

値に size を指定する例

inline-size を指定してコンテナ要素の幅に基づいてスタイルを適用することが多いと思いますが、コンテナクエリで条件(サイズ特性)に orientationaspect-ratio を指定する場合は、container-type の値に size を指定して、インライン方向及びブロック方向のサイズを対象とする必要があります。

以下は基準となるコンテナ要素(.bar-wrapper)が縦長か横長により、子要素(.bar)の背景色を切り替える例です。

<div class="bar-wrapper">
  <div class="bar">
    <p>bar</p>
  </div>
</div>

※ container-type: size を指定した場合、基準となるコンテナ要素に height を指定しないと表示されないので注意が必要です。

.bar-wrapper {
  /* size を指定してインライン方向及びブロック方向のサイズを対象に */
  container-type: size;
  /* height を指定しないと表示されないので注意 */
  height: 100px;
  border: 1px solid #999;
  /* コンテナ要素をリサイズ可能に(確認用) */
  resize: both;
  overflow: auto;
}

.bar {
  background-color: tomato;
  color: #fff;
  /* 基準となるコンテナの高さの100% */
  height: 100cqh;
}

.bar p {
  margin-block-start: 0;
}

/* クエリのサイズ特性に orientation を指定 */
@container (orientation: portrait) {
  .bar  {
    background-color: forestgreen;
  }
}

bar

container-name

container-name プロパティを使って、コンテナを識別するための名前を付けることができます。

名前を付けると、その名前を @container で使用することができ、特定のコンテナを対象とすることができます。

名前を指定しない場合には、コンテナコンテキストを持つ(container-type を指定した)最も近い祖先要素が対象になります。

任意の名前を付けることができますが、大文字と小文字は区別され、また、以下の条件があります。

  • 名前の値は引用符で囲んではいけない
  • スペースで区切られた複数の名前のリストを指定できます

@container で使用する際は、@container の後に名前を指定します。

.card-wrapper {
  container-type: inline-size;
  /* コンテナ(コンテキスト)に名前を指定 */
  container-name: card-wrapper-container;
}

/* 名前を指定してコンテナクエリを定義 */
@container card-wrapper-container (width >=420px) {
  .card {
    flex-direction: row;
  }
}

container

container プロパティは container-name と container-type を一括指定するためのショートハンドプロパティで、コンテナ名 / コンテナタイプ のように値を / で区切って指定します。

例えば、以下は

.card-wrapper {
  container-type: inline-size;
  container-name: card-wrapper-container;
}

以下のようにまとめて記述できます。

.card-wrapper {
  container: card-wrapper-container / inline-size;
}

@container ルール

@container はコンテナに対して評価される特性(条件)を指定してスタイルを適用するルールです。

以下が構文です。

@container 条件 {
  CSS
}

/* container-name で設定したコンテナ名を指定する場合 */
@container コンテナ名 条件 {
  CSS
}
  • 条件:コンテナのサイズが変更されたときに、コンテナに対して評価される特性の集合
  • CSS:指定した条件が真であれば(マッチすれば)適用されるスタイル

論理キーワード

コンテナクエリの条件では論理演算子の and と or 及び not が使えます。但し、コンテナクエリあたり1つの not だけが許されており、 and または or キーワードと同時に使用することはできません。

@container (width > 400px) and (height > 400px) {
  /* 適用されるスタイル */
}

@container (width > 400px) or (height > 400px) {
  /* 適用されるスタイル */
}

@container not (width < 400px) {
  /* 適用されるスタイル */
}

比較演算子

サイズ特性クエリで比較演算子(=、<、<=、>、>=)が使用できます。

例えば、以下の min-、max- 接頭辞を使用した記述は

@container (max-width: 400px) {
  /* 幅 400px 以下 */
}
@container (min-width: 401px) {
  /* 幅 401px 以上( 400px より大きい) */
}

以下のように比較演算子を使って記述することができます。

@container (width <= 400px) {
  /* 幅 400px 以下 */
}
@container (width > 400px) {
  /* 幅が 400px より大きい */
}

また、比較演算子を使って以下のような記述も可能です。

@container (300px < width <= 640px) {
  /* 幅 300px より大きく 640px 以下 */
}

/* 上記は以下とほぼ同じこと */
@container (min-width: 301px) and (max-width: 640px) {
  /* 幅 300px より大きく(301px 以上) 640px 以下 */
}

Media Queries Level 4 より、メディアクエリでも比較演算子(=、<、<=、>、>=)が使用できるようになっています(https://caniuse.com/css-media-range-syntax)。

サイズ特性

コンテナクエリで指定できるサイズ特性の記述子は以下になります。

指定できるサイズ特性の記述子
記述子 説明
width 横幅
height 高さ
inline-size インラインサイズ(横書きでは水平方向、縦書きでは垂直方のサイズ)
block-size ブロックサイズ(横書きでは垂直方向、縦書きでは水平方向のサイズ)
aspect-ratio アスペクト比
orientation portrait(縦長)または landscape(横長)

コンテナクエリの長さ単位

コンテナクエリでスタイルを設定する場合、以下のコンテナクエリの長さ単位(クエリするコンテナのサイズに相対する長さ)を使用することができます。

これらを使用することで、基準となるコンテナ要素の幅や高さに応じたサイズ指定が可能です。

単位 説明
cqw 基準となるコンテナ要素の幅の 1%
cqh 基準となるコンテナ要素の高さの 1%
cqi 基準となるコンテナ要素のインラインサイズの 1%
cqb 基準となるコンテナ要素のブロックサイズの 1%
cqmin cqi または cqb の小さい方
cqmax cqi または cqb の大きい方