0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

メディアクエリからコンテナクエリへ:レスポンシブ設計の新常識を解説

0
Posted at

はじめに

レスポンシブデザインといえば、長らく「メディアクエリで画面幅ごとにスタイルを切り替える」のが常識でした。

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

しかしこの方法には、コンポーネント時代の開発と根本的に相性が悪い問題があります。それを解決するのが コンテナクエリ(Container Queries) です。2026年現在、全主要ブラウザ(Chrome / Firefox / Edge / Safari)で利用可能になり、実務投入のハードルは完全になくなりました。

この記事では、メディアクエリの何が問題だったのか、コンテナクエリでどう変わるのかを、実装例を交えて解説します。

メディアクエリの限界:「画面幅」しか見えない

メディアクエリが見ているのは ビューポート(画面全体)の幅 です。しかし現代のUIはコンポーネント単位で作られ、同じコンポーネントがさまざまな場所で使い回されます。

例えば、こんな Card コンポーネントを考えます。

  • メインカラム(幅800px)では 横並びレイアウト で表示したい
  • サイドバー(幅300px)では 縦積みレイアウト で表示したい

メディアクエリではこれが素直に書けません。画面幅が1200pxのとき、メインカラムのカードもサイドバーのカードも「同じ画面幅」として扱われるからです。結果として:

/* こういう配置依存のクラスが増殖していく… */
.card--in-sidebar { ... }
.card--in-main { ... }
.card--in-modal { ... }

「どこに置かれるか」をコンポーネント自身が知らなければならず、再利用性が崩壊します。JSで親要素の幅を監視する(ResizeObserver)という力技もありますが、本来スタイルの問題にJSを持ち出すのは避けたいところです。

コンテナクエリ:「自分が置かれた場所」に反応する

コンテナクエリは、ビューポートではなく 親コンテナの幅 を基準にスタイルを切り替えます。

基本の書き方

ステップは2つだけです。

① 親要素を「コンテナ」として宣言する

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

@container でコンテナ幅に応じたスタイルを書く

.card {
  display: grid;
  grid-template-rows: 200px auto; /* デフォルトは縦積み */
}

@container (min-width: 400px) {
  .card {
    grid-template-rows: none;
    grid-template-columns: 160px 1fr; /* 広ければ横並び */
  }
}

これだけで、同じCardコンポーネントが、メインカラムでは横並び、サイドバーでは縦積み に自動で切り替わります。カード自身は「自分がどのページのどこに置かれているか」を一切知る必要がありません。

コンテナに名前をつける

コンテナが入れ子になる場合は、名前をつけて明示的に参照できます。

.sidebar {
  container-name: sidebar;
  container-type: inline-size;
  /* ショートハンド: container: sidebar / inline-size; */
}

@container sidebar (min-width: 250px) {
  .widget {
    padding: 1.5rem;
  }
}

コンテナクエリ専用の単位

コンテナ基準の相対単位も使えます。vw / vh のコンテナ版です。

単位 意味
cqw コンテナ幅の1%
cqh コンテナ高さの1%
cqi コンテナのインラインサイズの1%
cqmin / cqmax cqi / cqb の小さい方・大きい方
.card-title {
  /* コンテナ幅に応じてフォントサイズが滑らかに変わる */
  font-size: clamp(1rem, 4cqi, 1.5rem);
}

メディアクエリのブレークポイントを待たずに、コンテナ幅へ流動的に追従するタイポグラフィが実現できます。

実践例:1つのCardを3つの文脈で使い回す

<main class="main-column">
  <div class="card-wrapper"><article class="card"></article></div>
</main>
<aside class="sidebar">
  <div class="card-wrapper"><article class="card"></article></div>
</aside>
/* すべてのラッパーをコンテナ化 */
.card-wrapper {
  container-type: inline-size;
}

/* --- Cardコンポーネント(配置場所を知らない) --- */
.card {
  display: grid;
  gap: 0.75rem;
}

.card img {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

/* 400px以上あれば横並び */
@container (min-width: 400px) {
  .card {
    grid-template-columns: 160px 1fr;
    align-items: center;
  }
}

/* 600px以上あればさらにリッチに */
@container (min-width: 600px) {
  .card {
    grid-template-columns: 240px 1fr;
    gap: 1.5rem;
  }
  .card .description {
    display: block; /* 狭い場所では非表示だった説明文を表示 */
  }
}

CSSはコンポーネントに1回書くだけ。あとはどこに置いても勝手に最適なレイアウトになります。

では、メディアクエリは不要になるのか?

なりません。役割分担が明確になった、というのが正しい理解です。

用途 使うべきもの
ページ全体のレイアウト(カラム数、サイドバーの有無) メディアクエリ
ダークモード、prefers-reduced-motion などユーザー設定 メディアクエリ
コンポーネント内部のレイアウト切り替え コンテナクエリ
コンポーネント内の流動的なサイズ調整 コンテナクエリ単位(cqi など)

「ページはメディアクエリ、コンポーネントはコンテナクエリ」 と覚えておけばOKです。ページレイアウトがビューポートに反応してカラム幅を変え、その中のコンポーネントはコンテナクエリで勝手に追従する——これが2026年のレスポンシブ設計の基本形です。

移行のポイントと注意点

1. container-type を指定した要素はサイズ封じ込めが効く

container-type: inline-size を指定すると、その要素にサイズの封じ込め(containment)が適用されます。具体的には、子要素の大きさに基づいて自身の幅を決められなくなる ため、floatwidth: max-content 的な挙動に依存しているレイアウトでは崩れる可能性があります。コンテナ化するのは「レイアウト上、幅が親から決まるラッパー要素」にするのが安全です。

2. コンテナ自身にはクエリが効かない

@container でスタイルを変えられるのは コンテナの子孫要素 です。コンテナ自身のスタイルを変えたい場合は、さらに外側にラッパーを用意します。

3. 段階的移行がしやすい

コンテナクエリは既存のメディアクエリと共存できます。新規コンポーネントから導入し、既存部分は触らない、という進め方が現実的です。全主要ブラウザ対応済みですが、古い環境も考慮するなら @supports が使えます。

@supports (container-type: inline-size) {
  /* コンテナクエリ前提のスタイル */
}

まとめ

  • メディアクエリは「画面幅」しか見えず、コンポーネントの再利用と相性が悪かった
  • コンテナクエリは「親コンテナの幅」に反応するので、コンポーネントが配置場所を知らなくてよくなる
  • cqi などのコンテナ単位で流動的なサイズ調整も可能
  • メディアクエリが不要になるわけではなく、ページ=メディアクエリ / コンポーネント=コンテナクエリ の役割分担へ
  • 2026年現在、全主要ブラウザ対応済みで実務投入に障害なし

コンポーネント駆動の開発(React / Vue / Web Components など)をしているなら、恩恵は特に大きいはずです。まずは使い回しの多いCardやリストアイテムから置き換えてみてください。

参考リンク

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?