CSSのContainer Queries(コンテナクエリ)の使い方



CSSのContainer Queries(コンテナクエリ)は、要素を基準としてスタイルを適応することができる機能です。
レスポンシブWebデザインのレイアウト構築をしていく際に便利に活用することができます。

これまでのレスポンシブWebデザインでは、@media(メディアクエリ)を使ってウィンドウのサイズを基準にレイアウト調整を行なっていましたが、ここでご紹介するコンテナクエリを使うと、任意の要素を基準としたレイアウトの調整も可能となります。

各コンテンツごとで細かな調整ができるということです。

以下、Webブラウザのサポート状況になります。

Can I use (CSS Container Queries)
https://caniuse.com/css-container-queries


それでは、CSSのContainer Queriesの使い方を、サンプルを交えてご紹介していきます。

Container Queriesの使い方

コンテナクエリの書き方は、そのままコンテナクエリを適応させる方法と、コンテナクエリを指定して適応させる方法と2パターンあります。


基本的な流れとしては、
@containerルールでスタイルを定義しておき、対象の要素にcontainerプロパティを使って値を指定して定義のスタイルを適応させます。

@containerルールは以下のように記述します。
引数には要素の幅を指定します。

@container (min-width: 620px) {
  //スタイルを記述
}



@containerルールの定義ができましたら、対象となる要素にcontainerプロパティ使って値を指定します。

.sample {
  container-type: inline-size;
  container-name: box-container;
}



container-typeプロパティは、「size」「inline-size」「normal」の3つの値が指定できます。
主に「inline-size」を指定することになりますが、inline-sizeは親要素の値の変更で子要素にスタイルを適応させる指定になります。
container-nameプロパティは、対象のコンテナクエリのスタイルを適応させるために、コンテナクエリの名前を指定します。

この2つのプロパティはcontainerプロパティとして、ショートハンドで書くこともできます。
ショートハンドは、先にcontainer-nameを記述し、半角スペースとスラッシュを入れてからcontainer-typeの記述という順番で書きます。

ショートハンド

container: box-container / inline-size;



container-nameプロパティは、書き方によっては必要ない場合もあります。

それではまず、シンプルにコンテナクエリを使う方法をみていきます。
まずはHTMLのサンプルコードから。

HTML

<main>

  <div class="box-layout">
    <div class="box-conts">
      <div class="box-img">
        <img src="images/sample.jpg" alt="sample image">
      </div>
      <div class="box-txt">
        <h2>title</h2>
        <p>Lorem ipsum dolor sit amet. Non facilis modi rem quas quia quo asperiores maxime ut doloribus maxime sed nobis earum id sint quaerat? In harum iusto ad atque ...</p>
      </div>
    </div>
  </div>
  
</main>



画像とテキストが横並びになるようなボックスの構造を構築してみました。

続いてはCSS。
CSSでは、@containerルールで引数に指定した横幅に合わせて、containerプロパティを定義してスタイルを適応させます。
以下、CSSのサンプルコードになります。

CSS

main {
  padding: 0 4%;
}

.box-layout {
  max-width: 1000px;
  margin: 2rem auto;
  container-type: inline-size;
}


.box-conts {
  background-color: #ffdddd;
  padding: 2rem;
}

.box-img {
  margin: 0 0 1.2rem;
}

.box-txt {
  flex: 1;
}

.box-txt h2 {
  font-size: 1.4rem;
}


@container (min-width: 620px) {

  .box-conts {
    background-color: #ddddff;
    display: flex;
    flex-direction: row;
    gap: 0 2rem; 
  }

  .box-img {
    margin: 0;
  }

  .box-txt h2 {
    font-size: 2rem;
  }

}



CSSはモバイルファーストの書き方で、ベースのスタイルから記述しています。
まずは全体的にレイアウトを整えたところで、親要素のCSSクラス「box-layout」にcontainer-typeプロパティ「container-type: inline-size;」を指定して、@containerの定義で子要素のスタイルを適応させます。

サンプルではコンテナクエリの引数を「min-width: 620px」としていますので、container-typeプロパティを指定した親要素の横幅が620px以上の場合にコンテナクエリのスタイルが適応されます。

CSSのContainer Queries(コンテナクエリ)を使ったレイアウト調整



シンプルにコンテナクエリを使う方法では、container-typeプロパティのみでcontainer-nameプロパティは必要ありませんでした。
container-nameプロパティは、コンテナクエリを指定する場合に使います。

コンテナクエリを指定する


複数のコンテナクエリを使ってデザインしていく場合は、コンテナクエリに名前を指定して定義していきます。
その時、どのコンテナクエリを使うかをcontainer-nameプロパティで指定します。

.box-layout {
  container-type: inline-size;
  container-name: box-container;
}



container-nameプロパティの名前は、@containerルールの定義で付ける任意の名前となります。
サンプルでは「box-container」としました。
コンテナクエリの定義にて、@containerの後に任意の名前を付けていきます。

@container box-container (min-width: 620px) {
  //スタイルを記述
}



また、プロパティの指定では前述したように、ショートハンド「container: box-container / inline-size;」で記述してもOKです。
こちらの方がスッキリするでしょう。

それではサンプルとして、画像とテキストの横並びを交互にするようなデザインを構築する場合で見ていきます。
まずはHTMLのサンプルコードから。

HTML

<main>

  <div class="box-layout box-odd">
    <div class="box-conts">
      <div class="box-img">
        <img src="images/sample.jpg" alt="sample image">
      </div>
      <div class="box-txt">
        <h2>title</h2>
        <p>Lorem ipsum dolor sit amet. Non facilis modi rem quas quia quo asperiores maxime ut doloribus maxime sed nobis earum id sint quaerat? In harum iusto ad atque ...</p>
      </div>
    </div>
  </div>

  <div class="box-layout box-even">
    <div class="box-conts">
      <div class="box-img">
        <img src="images/sample.jpg" alt="sample image">
      </div>
      <div class="box-txt">
        <h2>title</h2>
        <p>Lorem ipsum dolor sit amet. Non facilis modi rem quas quia quo asperiores maxime ut doloribus maxime sed nobis earum id sint quaerat? In harum iusto ad atque ...</p>
      </div>
    </div>
  </div>
  
</main>



先ほどのサンプルからボックスを1つ追加して、各ボックスに「box-odd」「box-even」という感じでクラスを追加しておきました。

続いてはCSS。
こちらも先ほどの親要素のCSSクラス「box-layout」のcontainer-typeプロパティの指定は、共通のスタイルとして使っていきます。

CSS

main {
  padding: 0 4%;
}

.box-layout {
  max-width: 1000px;
  margin: 2rem auto;
  container-type: inline-size;
}

.box-odd {
  container: box-layout-odd / inline-size;
}

.box-even {
  container: box-layout-even / inline-size;
}

.box-conts {
  background-color: #ffdddd;
  padding: 2rem;
}

.box-img {
  margin: 0 0 1.2rem;
}

.box-txt {
  flex: 1;
}

.box-txt h2 {
  font-size: 1.4rem;
}

@container (min-width: 620px) {

  .box-conts {
    background-color: #ddddff;
    display: flex;
    flex-direction: row;
    gap: 0 2rem; 
  }

  .box-img {
    margin: 0;
  }

  .box-txt h2 {
    font-size: 2rem;
  }

}

@container box-layout-odd (min-width: 620px) {

  .box-img {
    order: 1;
  }

  .box-txt {
    order: 2;
  }

}

@container box-layout-even (min-width: 620px) {

  .box-img {
    order: 2;
  }

  .box-txt {
    order: 1;
  }

}



全体的なデザインは先ほどと変わりません。
各ボックスのCSSクラス「box-odd」「box-even」には、「box-layout-odd」や「box-layout-even」といったcontainer-nameプロパティを指定してコンテナクエリを適応させています。
横並びのレイアウトはFlexboxで構築していますので、各コンテナクエリではflexのorderプロパティを使って、画像とテキストのHTML構造の順番を変えています。

CSSのContainer Queries(コンテナクエリ)を使った要素を交互に配置するレイアウト



orderプロパティについては、以下の記事でご紹介しています。



このように、奇数と偶数というかたちで、交互のレイアウトの構築もコンテナクエリで手軽にできます。

以下、ここまでの動作の流れです。
動画(4分20秒ほど)

まとめ


ウィンドウ幅かコンテンツ幅か、どちらを基準にレイアウト調整したいかでメディアクエリとコンテナクエリを使い分けるといいでしょう。

2カラムのWebページのレイアウトで、メインコンテンツとサイドバーと、全体的なコンテンツブロックのレイアウトはメディアクエリで調整し、各コンテンツの細かな部分で調整が必要な場合、Container Queries(コンテナクエリ)が便利に活用できるかと思います。