はじめに:94%がサポート済みなのに、なぜ使われないのか

CSSコンテナクエリは現在、ブラウザサポート率が約94%に達しています。しかしState of CSSの調査によると、開発者の86%が存在を認知しているにもかかわらず、実際に使用しているのは**41.4%**にとどまります。

なぜこのような乖離が生まれるのでしょうか。理由はシンプルです。コンテナクエリの文法がメディアクエリと酷似しているからです。見た目が似ているため「用途も似ているはず」と誤解されやすいのですが、両者は参照する方向が真逆です。

本記事では、メディアクエリとコンテナクエリの根本的な違いを整理し、実務でコンポーネントをどう設計すべきかをコードで確認します。(根拠資料:Smashing Magazine 原文)

Developer comparing CSS container queries and media queries on a code editor screen Development Concept Image

本質的な違い:メディアクエリは「外」を、コンテナクエリは「内」を見る

メディアクエリの限界

以下のコードをご覧ください。

@media (min-width: 1024px) {
  .card {
    display: flex;
  }
}

このコードはブラウザに対して、**「現在のビューポート幅はいくつか」**という一点だけを問い合わせています。

問題は、この .card が1920pxのデスクトップ画面内にある300pxのグリッドセルに配置された場合に発生します。ビューポートは依然として1920pxなので min-width: 1024px が発火し、幅300pxしかないカードに display: flex が適用されてレイアウトが崩壊します。

「メディアクエリは賢くない。概念が悪いのではなく、知っている情報が少なすぎるのだ」 — Kevin Powell

コンテナクエリに置き換えると

/* 親要素をコンテナとして登録 */
.card-wrapper {
  container-name: card;
  container-type: inline-size;
}

/* 親のインライン(横方向)サイズを基準に判定 */
@container card (min-width: 450px) {
  .card {
    display: flex;
    flex-direction: row;
  }
}

これでカードはビューポートを気にしません。**「親ラッパーが450px以上の横方向スペースを確保しているか」**だけを判定します。条件を満たせば横並び、満たさなければデフォルトの block 配置です。

実践例:ビューポートではなくコンポーネントに追従する流体タイポグラフィ

メディアクエリ時代は vw 単位でフォントサイズを調整していました。

/* ❌ ビューポート基準 — サイドバーに入れるとフォントが破綻 */
.card-title {
  font-size: clamp(100%, 1rem + 2vw, 24px);
}

コンテナクエリには専用の単位(cqi、cqw、cqb)があります。clamp() と組み合わせることで、コンポーネントサイズに応じた流体タイポグラフィが実現できます。

/* ✅ コンテナのインラインサイズ基準 */
.card-title {
  font-size: clamp(1rem, .5rem + 3cqi, 2rem);
}

これでカードをどこに配置しても、フォントは自身のコンテナ内で最適化されます。

Responsive card component layout adapting to container width in a browser devtools view Dev Environment Setup

注意点:コンテナクエリの3つの副作用

導入前に必ず把握しておくべき落とし穴があります。

1. コンテナは自身をクエリできない

/* ❌ 無限ループ — 動作しない */
.card {
  container-name: card;
  container-type: inline-size;
}
@container card (min-width: 400px) {
  .card { display: flex; }
}

コンテナが自身のサイズを見て自身を変更すると無限ループになるため、ブラウザがこれを禁止しています。必ず親ラッパーを1段追加し、そのラッパーをコンテナとして登録する必要があります。マークアップが1階層増えるトレードオフがあります。

2. container-type: size はレイアウトを崩壊させる可能性がある

/* ⚠️ 高さを明示しないと0pxに崩壊 */
.hero-banner {
  container-type: size;
}

size は縦横両方をクエリ対象にする指定ですが、ブラウザは子要素を参照せずにコンテナサイズを計算します。height や aspect-ratio を明示しないと高さが0になります。特別な理由がない限り、inline-size のみを使うのが安全です。

3. カスタムプロパティはクエリ条件に使用できない

:root { --breakpoint-lg: 1600px; }

/* ❌ 動作しない */
@container (min-width: var(--breakpoint-lg)) { /* ... */ }

カスタムプロパティはDOMを辿ってカスケードされる値であるため、クエリ条件内でその値が再度変化する可能性があります。ブラウザは循環参照を防ぐため、条件部での使用を禁止しています。ブレークポイントを変数管理していたチームには不便な仕様です。

どちらを使うべきか — マクロ vs ミクロ

  • メディアクエリ(マクロレイアウト): ページ全体構造、ヘッダー/フッター、メイングリッド、prefers-color-scheme、タッチスクリーン判定
  • コンテナクエリ(ミクロレイアウト): カード、ウィジェット、フォーム、ナビゲーションなど複数コンテキストで再利用されるコンポーネント

判断基準はシンプルです。**「このコンポーネントは1箇所でしか使われないか」ならメディアクエリ、「複数レイアウトで再利用されるか」**ならコンテナクエリです。

Frontend developer desk setup with browser responsive mode testing component layouts Technical Structure Concept

まとめ:ビューポートはあくまで「代理指標」にすぎない

これまでのレスポンシブデザインは、ビューポート幅という代理指標(proxy)に依存してきました。しかしモダンWebには2,300以上ものビューポートサイズが存在します。それをすべて想定するのは不可能です。

コンテナクエリは、レスポンシブデザインの基準を**「画面」から「コンポーネントの実際のスペース」へ**移行させます。これこそが本質的に正しい方向性です。

日本の開発エコシステムにおける適用文脈

日本の受託開発やSaaS開発では、デザインシステムや共通コンポーネントライブラリを運用するチームにとって特に有効です。ただし以下の2点は事前に確認してください。

  1. レガシーブラウザ対応: 94%のサポート率は優秀ですが、官公庁系や金融系プロジェクトで旧Edge対応が必要な場合は、@supports による分岐が必須です。
  2. マークアップのラッパー増加: コンテナは自身をクエリできないため、ラッパー <div> が1つ増えます。HTMLコーダーと分業する現場では、マークアップ規約を事前に合意しておくと安全です。

次のステップ学習方向

  • Container Style Queries: 計算済みスタイルに反応する次世代機能(現在実験段階)
  • :has() セレクタとの組み合わせ: 親の状態に応じた条件付きスタイリング
  • CSS Nesting + @container: コンポーネント単位のCSSカプセル化パターン

あわせて読みたい記事

本コンテンツは、信頼性の高い情報源をもとにAIツールを活用して作成され、編集者によるレビューを経て公開されています。専門家によるアドバイスの代替となるものではありません。