あなたに合った学習プランは?LINE適正コース診断はこちら プログラミングが全て無料で学習可能!
【CSS】コンテナクエリとメディアクエリの違いとは?使い分けと書き方 - 忍者CODEマガジン

【CSS】コンテナクエリとメディアクエリの違いとは?使い分けと書き方

プログラミング言語の辞書

レスポンシブ対応といえば、これまではメディアクエリを使って画面幅ごとにCSSを切り替える方法が定番でした。しかし、同じカード部品をメインカラムとサイドバーの両方で使う場合、画面幅だけではうまく調整できない経験はありませんか?そこで役立つのがコンテナクエリです。コンテナクエリを使うと、画面全体の幅ではなく、親要素やコンテナの幅に応じてCSSを切り替えられます。

メディアクエリは「画面幅」を基準にし、コンテナクエリは「部品が入っている箱の幅」を基準にしてCSSを切り替える仕組みです。この記事では、それぞれの違い、使い分け、基本の書き方、効かない原因まで解説します。

  1. メディアクエリとコンテナクエリの違い
  2. 視覚的なイメージ:メディアクエリ vs コンテナクエリ
  3. メディアクエリとは?画面幅を基準にする方法
    1. メディアクエリが向いている場面
  4. コンテナクエリとは?親要素の幅を基準にする方法
    1. コンテナクエリの基本コード
    2. 【注意】container-typeに「size」ではなく「inline-size」を使う理由
  5. どちらを使う?実務での使い分け
    1. ページ全体はメディアクエリ
    2. 部品単位はコンテナクエリ
  6. 名前付きコンテナを使う方法
    1. containerショートハンドも使える
  7. コンテナクエリが効かない原因と対策
    1. 原因1:親要素にcontainer-typeを書いていない
    2. 原因2:自分自身の幅を条件にしようとしている
    3. 原因3:メディアクエリと役割が混ざっている
  8. コンテナクエリとclamp()を組み合わせる
  9. 実務で差が出るコンテナクエリの使いどころ
    1. 例:同じカードをメインカラムとサイドバーで使う
  10. メディアクエリとコンテナクエリを併用する実装例
    1. 役割を分けるとCSSの読みやすさが上がる
  11. コンテナクエリのフォールバックは必要?
  12. コンテナクエリをデバッグするときの確認手順
    1. 1. container-typeが親要素に付いているか
    2. 2. 条件にしている幅が現実的か
    3. 3. 対象要素とコンテナの親子関係を確認する
  13. コンテナクエリを使う判断チェックリスト
  14. 公式ドキュメントも確認する
  15. まとめ:画面全体はメディアクエリ、部品単位はコンテナクエリ

メディアクエリとコンテナクエリの違い

まずは、2つの違いをシンプルに整理しましょう。

項目 メディアクエリ コンテナクエリ
基準 画面幅・端末条件 親要素やコンテナのサイズ
書き方 @media @container
向いているもの ページ全体のレイアウト変更 部品単位の見た目変更
よく使う例 PCでは2カラム、スマホでは1カラム カード幅が狭いときだけ縦並びにする

メディアクエリは、ページ全体のレイアウトを切り替えるときに便利です。一方、コンテナクエリは、同じ部品を別の場所でも使い回したいときに力を発揮します。

視覚的なイメージ:メディアクエリ vs コンテナクエリ

言葉だけではイメージしづらい「コンテナクエリのメリット」を、以下の図解例で見てみましょう。同じカードコンポーネントを、広い場所と狭い場所に置いた場合の挙動の違いです。

① メインカラム(広いコンテナ)

→ 横に広がる(リッチな表示)

② サイドバー(狭いコンテナ)

→ 縦に並ぶ(コンパクト表示)

ここがポイント!
メディアクエリだと「画面の幅」しか見ないため、PC画面で見ている限り、どちらも同じ見た目になってしまいます。コンテナクエリなら、「置かれた場所の幅」に合わせて、パーツが勝手に最適な形に変身してくれます。

メディアクエリとは?画面幅を基準にする方法

メディアクエリは、画面幅や端末の条件に応じてCSSを切り替える書き方です。

.layout {
  display: block;
}

@media (min-width: 768px) {
  .layout {
    display: grid;
    grid-template-columns: 2fr 1fr;
    gap: 32px;
  }
}

この例では、画面幅が768px以上になったときに、レイアウトを1カラムから2カラムへ切り替えています。

メディアクエリが向いている場面

メディアクエリは、ページ全体の構造を変えるときに向いています。

  • スマホとPCでページ全体の余白を変える
  • PCだけサイドバーを表示する
  • ヘッダーのナビゲーションをスマホだけ折りたたむ
  • 画面幅に応じてグリッドの列数を変える

画面全体のレイアウトを切り替えるなら、まずはメディアクエリを使うのが基本です。

コンテナクエリとは?親要素の幅を基準にする方法

コンテナクエリは、指定したコンテナのサイズに応じて、内側の要素のCSSを切り替える仕組みです。たとえば、同じカードをメインカラムでは横並び、サイドバーでは縦並びにしたい場合、画面幅だけを基準にすると調整が難しくなります。

コンテナクエリの基本コード

コンテナクエリを使うには、まず親要素にcontainer-typeを指定します。

<div class="card-area">
  <article class="profile-card">
    <img src="profile.jpg" alt="プロフィール写真">
    <div>
      <h3>忍者太郎</h3>
      <p>フロントエンド学習中です。</p>
    </div>
  </article>
</div>
.card-area {
  container-type: inline-size;
}

.profile-card {
  display: grid;
  gap: 16px;
}

@container (min-width: 480px) {
  .profile-card {
    grid-template-columns: 120px 1fr;
    align-items: center;
  }
}

このコードでは、.card-areaの横幅が480px以上になったときだけ、カード内のレイアウトが横並びになります。

コンテナクエリは、対象要素そのものではなく、親側のコンテナサイズを見て切り替える点が重要です。

【注意】container-typeに「size」ではなく「inline-size」を使う理由

コンテナクエリを使う際、container-type に指定できる値には主に以下の2つがあります。

監視する対象
inline-size 親要素の横幅(インライン方向)だけを基準にする(★基本はこれ)
size 親要素の縦幅と横幅の両方を基準にする

一見すると、縦も横も監視できる size の方が便利そうに見えますが、実務のレスポンシブ対応ではほぼ100% inline-size を使用します。

「size」を使うとレイアウトが無限ループする危険性がある

もし size を指定して「縦幅」まで監視してしまうと、以下のようなバグ(無限ループ)が起きやすくなります。

  1. 親要素の縦幅が変わる
  2. コンテナクエリが反応して、中の文字サイズや高さを変える
  3. 中のサイズが変わったことで、さらに親要素の縦幅が変わる
  4. それに反応して、またコンテナクエリが動く……(無限ループでブラウザがフリーズする原因に)

Webサイトは基本的に上から下へスクロールする構造(横幅は固定で縦に伸びる)のため、横幅だけを監視する inline-size を選ぶのが鉄則です。「コンテナクエリの基本は inline-size」とセットで覚えておきましょう。

どちらを使う?実務での使い分け

コンテナクエリとメディアクエリは、どちらか一方だけを使うものではありません。役割を分けて併用するのが現実的です。

ページ全体はメディアクエリ

ページ全体の余白、ヘッダーの表示、メインカラムとサイドバーの有無などは、メディアクエリで管理すると分かりやすいです。

.page {
  padding: 24px;
}

@media (min-width: 1024px) {
  .page {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 320px;
    gap: 40px;
  }
}

部品単位はコンテナクエリ

カード、商品リスト、プロフィール枠、料金プランなど、別の場所でも使い回す部品は、コンテナクエリで自立させると便利です。

.product-list {
  container-type: inline-size;
}

.product-card {
  display: grid;
  gap: 12px;
}

@container (min-width: 560px) {
  .product-card {
    grid-template-columns: 180px 1fr;
  }
}

ページの大きな切り替えはメディアクエリ、再利用する部品の調整はコンテナクエリ、と分けると設計しやすくなります。

名前付きコンテナを使う方法

複数のコンテナがある場合は、container-nameで名前を付けると管理しやすくなります。

.sidebar {
  container-type: inline-size;
  container-name: sidebar;
}

@container sidebar (max-width: 360px) {
  .ranking-card {
    font-size: 0.875rem;
  }
}

このように書くと、sidebarという名前のコンテナだけを対象にできます。

containerショートハンドも使える

container-namecontainer-typeは、まとめて書くこともできます。

.sidebar {
  container: sidebar / inline-size;
}

短く書けますが、初心者のうちはcontainer-typecontainer-nameを分けて書いた方が意味を追いやすいです。

コンテナクエリが効かない原因と対策

原因1:親要素にcontainer-typeを書いていない

コンテナクエリを使うには、基準にしたい親要素へcontainer-typeを指定する必要があります。

【NG例】
.card-area {
  /* container-typeがない */
}

@container (min-width: 480px) {
  .card {
    display: flex;
  }
}
【OK例】
.card-area {
  container-type: inline-size;
}

@container (min-width: 480px) {
  .card {
    display: flex;
  }
}

原因2:自分自身の幅を条件にしようとしている

コンテナクエリは、基本的にコンテナの内側にある要素を切り替えるためのものです。対象要素自身ではなく、親要素をコンテナとして設定しましょう。

原因3:メディアクエリと役割が混ざっている

ページ全体のレイアウト変更までコンテナクエリで行おうとすると、CSSの意図が分かりにくくなります。画面全体の条件は@media、部品の横幅条件は@containerに分けると整理できます。

コンテナクエリとclamp()を組み合わせる

コンテナクエリは、clamp()max-widthと組み合わせると、より自然なレスポンシブ設計ができます。

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

.card-title {
  font-size: clamp(1.125rem, 4cqi, 1.75rem);
}

@container (min-width: 560px) {
  .card {
    grid-template-columns: 200px 1fr;
  }
}

cqiはコンテナのインライン方向のサイズに基づく単位です。画面全体ではなく、コンテナ幅に合わせて文字サイズを調整したいときに使えます。

コンテナ単位は便利ですが、初学者のうちはまず@containercontainer-typeの基本から押さえましょう。

実務で差が出るコンテナクエリの使いどころ

コンテナクエリが特に役立つのは、「同じ部品を複数の場所で使い回す」場面です。画面幅だけでCSSを切り替えるメディアクエリでは、部品が置かれた場所の幅までは判断できません。

例:同じカードをメインカラムとサイドバーで使う

たとえば、記事カードをメインカラムにもサイドバーにも表示するケースを考えます。

<main class="main-column">
  <div class="article-card-wrap">
    <article class="article-card">
      <img src="thumb.jpg" alt="">
      <div>
        <h3>記事タイトル</h3>
        <p>記事の説明文が入ります。</p>
      </div>
    </article>
  </div>
</main>

<aside class="sidebar">
  <div class="article-card-wrap">
    <article class="article-card">
      <img src="thumb.jpg" alt="">
      <div>
        <h3>記事タイトル</h3>
        <p>記事の説明文が入ります。</p>
      </div>
    </article>
  </div>
</aside>

同じ.article-cardでも、メインカラムでは横幅が広く、サイドバーでは狭くなります。このような場合、画面幅ではなくカードの親要素の幅を基準にする方が自然です。

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

.article-card {
  display: grid;
  gap: 12px;
}

@container (min-width: 520px) {
  .article-card {
    grid-template-columns: 180px 1fr;
    align-items: start;
  }
}

この書き方なら、画面幅が同じでも、カードの置き場所に合わせて縦並び・横並びを切り替えられます。

コンテナクエリは、再利用する部品を「置かれた場所の幅」に合わせて自動調整したいときに強いCSSです。

メディアクエリとコンテナクエリを併用する実装例

メディアクエリとコンテナクエリは、競合する機能ではありません。ページ全体の大枠はメディアクエリで作り、部品の中身はコンテナクエリで調整すると、保守しやすくなります。

.page-layout {
  display: grid;
  gap: 24px;
}

@media (min-width: 1024px) {
  .page-layout {
    grid-template-columns: minmax(0, 1fr) 320px;
    gap: 40px;
  }
}

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

.article-card {
  display: grid;
  gap: 16px;
}

@container (min-width: 560px) {
  .article-card {
    grid-template-columns: 200px 1fr;
  }
}

このコードでは、ページ全体の2カラム化は@media、カード内部の横並び化は@containerが担当しています。

役割を分けるとCSSの読みやすさが上がる

すべてをメディアクエリで書くと、「1024px以上ならカードを横並びにする」という条件になりがちです。しかし、実際には1024px以上でもサイドバー内のカードは狭いままです。

コンテナクエリを使うと、「カードが入っている場所が広いなら横並び」という条件にできます。これは部品目線の条件なので、デザインの意図に近い書き方です。

オススメ:HTML、CSSの問題集に無料で挑戦しよう!
HTMLを勉強していると、調べれば分かることもありますが、実際に自分でアウトプットするのは難しいと感じることがあります。
忍者CODEのHTML、CSS 学習の無料問題集では、HTML、CSSに関する問題を用意しています。

コンテナクエリのフォールバックは必要?

現在の主要ブラウザではコンテナクエリを使える環境が増えていますが、案件によっては古いブラウザ対応を求められることがあります。

古い環境まで考える場合は、まず通常のCSSで縦並びの安全な見た目を作り、対応ブラウザではコンテナクエリで横並びにするのが基本です。

.article-card {
  display: grid;
  gap: 16px;
}

@supports (container-type: inline-size) {
  .article-card-wrap {
    container-type: inline-size;
  }

  @container (min-width: 560px) {
    .article-card {
      grid-template-columns: 200px 1fr;
    }
  }
}

このように@supportsを使うと、コンテナクエリに対応している環境だけ追加スタイルを適用できます。

古いブラウザ対応が必要な案件では、コンテナクエリが使えない状態でも読める・崩れない基本レイアウトを先に作りましょう。

コンテナクエリをデバッグするときの確認手順

コンテナクエリが効かないときは、次の順番で確認すると原因を見つけやすくなります。

1. container-typeが親要素に付いているか

最も多いミスは、@containerだけを書いて、基準となる親要素にcontainer-typeを書き忘れることです。

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

検証ツールで親要素を選択し、container-typeが実際に当たっているか確認しましょう。

2. 条件にしている幅が現実的か

@container (min-width: 800px)のように大きすぎる条件を書いていると、サイドバーや小さなカード枠では永遠に条件を満たしません。

@container (min-width: 420px) {
  .card {
    grid-template-columns: 140px 1fr;
  }
}

カード部品なら、まず400px600pxあたりで試すと変化を確認しやすいです。

3. 対象要素とコンテナの親子関係を確認する

コンテナクエリは、コンテナの中にある要素へ適用します。対象要素がコンテナの外にある場合、条件に反応しません。

【NG例】
<div class="card-wrap"></div>
<article class="card">カード</article>
【OK例】
<div class="card-wrap">
  <article class="card">カード</article>
</div>

コンテナクエリを使う判断チェックリスト

質問 YESなら おすすめ
ページ全体の構造を変えたい? 画面幅が基準になる メディアクエリ
同じ部品を複数箇所で使う? 置き場所で幅が変わる コンテナクエリ
サイドバー内だけ見た目が崩れる? 部品の横幅が狭い可能性が高い コンテナクエリ
ヘッダー全体をスマホ用にしたい? 画面幅で切り替える メディアクエリ
カードの中の画像と文章だけ切り替えたい? 部品内部の調整 コンテナクエリ

公式ドキュメントも確認する

コンテナクエリは比較的新しいCSS機能です。実務で使う場合は、公式ドキュメントや対応ブラウザも確認しておきましょう。

まとめ:画面全体はメディアクエリ、部品単位はコンテナクエリ

この記事では、コンテナクエリとメディアクエリの違いについて解説しました。

メディアクエリは画面幅、コンテナクエリは親要素の幅を基準にCSSを切り替える仕組みです。

ページ全体のレイアウト変更にはメディアクエリ、カードや商品リストなど部品単位の調整にはコンテナクエリを使うと、再利用しやすいCSSになります。

まずはcontainer-type: inline-size;@containerの組み合わせから試してみましょう。