コンテナクエリ(2022年新機能)

コンテナクエリ(2022年新機能)

コンテナクエリとは

これまでのレスポンシブデザインでは画面幅(ブラウザ幅)を基準にブレイクポイントを決め、それに応じてスタイルを定義するメディアクエリを使用していましたが、コンテナクエリでは指定した親コンテナをベースにして子要素のスタイルを定義できます。

これが使えるようになることで、ブラウザ幅に影響されることなく親コンテナのサイズに合わせて文字の大きさを変えるといったことなどができるようになり、より柔軟なレスポンシブデザインが作れます。

使用可能ブラウザとポリフィル

2022年10月現在、Chrome 105+(Edgeも105+)とSafari 16に対応。

ポリフィルもあり、Chrome/Edge 88+, Firefox 78+, Safari 14+をカバーしています。
Container Query Polyfill -GitHub

直接CDNを読み込んでもいいのですが、下のコードを記述すると、コンテナクエリ未対応のブラウザにのみポリフィルが読み込まれるようになるのでオススメ。

// 直接CDNを読み込む
<script src="https://cdn.jsdelivr.net/npm/container-query-polyfill@1/dist/container-query-polyfill.modern.js"></script>

// 未対応の時のみ読み込む
<script>
const supportsContainerQueries = "container" in document.documentElement.style;
 
if (!supportsContainerQueries) {
  import("https://cdn.skypack.dev/container-query-polyfill");
}
</script>

使い方

コンテナクエリの親コンテナとなる要素にはスタイルを定義してはいけないというルールがあります。そのため場合によってはコンテナクエリ用のラッパー要素を用意してから、親コンテナですよと定義します。

<div class="parent-wrap">
  <div class="container">
    <div class="child-content">
      <p>親譲りの無鉄砲で小供の時から損ばかりしている。</p>
    </div>
  </div>
</div>
.parent-wrap {
  container: inline-size / parent-wrap; /* ショートハンド */
  /* container-type: inline-size; */
  /* container-name: parent-wrapper; 個別にコンテナクエリを指定する場合は名前をつける */
}

そして、メディアクエリと同じような感じで子要素のスタイルを定義します。

.child-content p {
  color: red;
}

/* 個別にコンテナクエリを指定する場合 */
/* @conteiner [container-name] (max-width: [size]) */
@container parent-wrapper (max-width: 700px) {
  .child-content p {
    color: blue;
  }
}

/* まとめてコンテナクエリを指定する場合 */
/* @conteiner (max-width: [size]) */
@container (max-width: 700px) {
  .child-content p {
    color: blue;
  }
}

これを実行すると、親要素である .parent-wrap の幅が700px以下のときに文字色は青となり、701px以上で赤となります。
まとめてコンテナクエリを指定する場合は親要素の container-name を指定する必要はなく、自動的に子要素から一番近い container-type: inline-size; を指定した親要素がベースとなります。

コンテナクエリの新しい単位

親要素にコンテナさえ指定しておけば、コンテナベースの単位を使うことができます。
単位の最初にcontainer queryの「cq」がついてるので分かりやすい。

cqwコンテナの幅の1%
cqhコンテナの高さの1%
cqiコンテナのインラインサイズの1%
cqbコンテナのブロックサイズの1%
cqmincqiまたはcqbの小さい方の値
cqmaxcqiまたはcqbの大きい方の値