はじめに:レスポンシブデザインの新たな地平

これまでレスポンシブデザインといえば、主にCSSメディアクエリが使われてきました。しかし、メディアクエリはページのビューポート(表示領域)全体のサイズを基準にするため、コンポーネント単位での柔軟なレイアウト変更には限界がありました。同じカードコンポーネントでも、サイドバーに置くかメインコンテンツに置くかで見た目を変えたい、でもそれをCSSだけで完結させるのは困難でした。

この課題を解決するのが「CSSコンテナクエリ」です。コンテナクエリは、ビューポートではなく、コンポーネントが配置されている親要素(コンテナ)のサイズに基づいてスタイルを適用できます。これにより、コンポーネントは自身の置かれた環境に応じて自己のスタイルを決定でき、真に独立した再利用可能な部品となるのです。この記事では、コンテナクエリの基本から実践的な使い方までを解説します。

コンテナクエリの基本的な使い方

コンテナクエリを使い始めるのは非常に簡単です。まず、基準としたい親要素を「コンテナ」として定義する必要があります。これにはcontainer-typeプロパティを使用します。

最も一般的に使われるのは、要素のインライン方向(通常は横幅)のサイズをコンテナクエリの基準とするinline-sizeです。

/* コンテナとなる要素を定義 */
.card-wrapper {
  container-type: inline-size;
  container-name: card-container; /* オプショナルだが名前を付けると管理しやすい */
}

コンテナを定義したら、@containerルールを使って、そのコンテナのサイズに応じたスタイルを記述します。構文はメディアクエリと非常によく似ています。

/* コンテナの幅が400px以上の場合にスタイルを適用 */
@container card-container (min-width: 400px) {
  .card {
    background-color: lightblue;
  }
}

container-nameで名前を付けた場合は、@container 名前 (条件)のように指定します。名前を付けないと、最も近い親コンテナが自動的に対象となりますが、入れ子構造が複雑になると意図しない動作をすることがあるため、名前を付けておくのがベストプラクティスです。

実践!カードコンポーネントで見るコンテナクエリ

それでは、具体的なカードコンポーネントでコンテナクエリの威力を見てみましょう。このカードは、狭いコンテナでは画像を上、テキストを下にした縦積みレイアウト、広いコンテナでは画像を左、テキストを右にした横並びレイアウトに変化させます。

HTML:

<div class="card-container">
  <article class="card">
    <img src="image.jpg" alt="" class="card-image">
    <div class="card-body">
      <h3>コンテナクエリ</h3>
      <p>コンポーネントが自身のコンテナサイズに応じてレイアウトを変更します。</p>
    </div>
  </article>
</div>

CSS:

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

.card {
  display: grid;
  grid-template-columns: 1fr;
  border: 1px solid #ccc;
  border-radius: 8px;
  overflow: hidden;
}

/* コンテナの幅が 30rem 以上になったらレイアウト変更 */
@container (min-width: 30rem) {
  .card {
    grid-template-columns: 1fr 2fr;
  }
}

このCSSだけで、.card-containerの幅が30remを超えるかどうかで、.cardのレイアウトが自動的に切り替わります。このコンポーネントを幅の狭いサイドバーや広いメインコンテンツエリアのどちらに配置しても、最適な見た目を保つことができるのです。

コンテナ相対単位で実現する流動的なタイポグラフィ

コンテナクエリには、コンテナのサイズを基準とした新しい相対単位が導入されました。これらを使うことで、よりきめ細やかなレスポンシブ対応が可能になります。

  • cqw: コンテナの幅の1%
  • cqh: コンテナの高さの1%
  • cqi: コンテナのインラインサイズ(横書きなら幅)の1%
  • cqb: コンテナのブロックサイズ(横書きなら高さ)の1%
  • cqmin: cqiとcqbの小さい方の値
  • cqmax: cqiとcqbの大きい方の値

特に強力なのが、フォントサイズへの応用です。例えば、cqi単位とclamp()関数を組み合わせることで、コンテナのサイズ変更に応じて滑らかに文字サイズが変わる「流動的なタイポグラフィ」を実現できます。

@container (min-width: 30rem) {
  .card h3 {
    /* 
      フォントサイズを最小1.25rem, 最大1.75remに保ちつつ、
      基本はコンテナ幅の4%を基準にスケーリングさせる
    */
    font-size: clamp(1.25rem, 4cqi + 0.5rem, 1.75rem);
  }
}

これにより、ブレークポイント間でフォントサイズがカクカクと変わるのではなく、リサイズに合わせてスムーズに拡大・縮小します。コンポーネント内の余白(paddingやmargin)にも応用でき、コンポーネント全体の調和を保ったままスケーリングさせることが可能です。

まとめ:コンテナクエリで変わるコンポーネント設計

CSSコンテナクエリは、コンポーネントが自身の置かれた文脈(コンテナのサイズ)を認識し、自律的にスタイルを変化させることを可能にする画期的な技術です。これにより、私たちは以下のような大きなメリットを得られます。

  • 再利用性の向上: どんなレイアウトの場所に置かれても、コンポーネントが自動で最適化されるため、再利用性が劇的に向上します。
  • 関心の分離: ページのレイアウトとコンポーネントの内部レイアウトを明確に分離できます。
  • 宣言的な記述: JavaScriptに頼ることなく、CSSだけで複雑なレスポンシブ挙動を宣言的に記述できます。

今後のWeb開発では、「ページ全体のマクロなレイアウトはメディアクエリ、コンポーネント単位のミクロなレイアウトはコンテナクエリ」という使い分けが主流になるでしょう。モダンブラウザではすでに広くサポートされており、今すぐプロジェクトに導入できます。ぜひコンテナクエリをマスターして、一歩先のコンポーネント設計を実践してみてください。