コンテナクエリを使う

従来のメディアクエリよりも柔軟で効率的なレスポンシブデザインを実現するコンテナクエリの使い方と利点について解説します。

概要

コンテナクエリ(Container Queries)は、要素自身のサイズに基づいてスタイルを適用できるCSS機能です。従来のメディアクエリがビューポート全体のサイズに依存するのに対し、コンテナクエリは親要素のサイズに応じてスタイルを変更できるため、よりモジュラーで再利用可能なコンポーネントの作成が可能になります。

コンテナクエリを使う理由

より柔軟なコンポーネント設計

従来のメディアクエリではビューポート全体のサイズしか参照できませんでしたが、コンテナクエリを使用することで、コンポーネントが配置される実際のコンテナサイズに基づいてスタイルを決定できます。

これにより、ビューポートサイズではなく、コンポーネントが実際に占有するスペースに基づいてレイアウトを決定できるため、より精密で直感的なデザイン制御が可能です。

メディアクエリとの使い分け

コンテナクエリはメディアクエリを完全に置き換えるものではありません。以下のような使い分けが推奨されます:

  • メディアクエリ: ページ全体のレイアウトやposition: fixed要素
  • コンテナクエリ: 個々のコンポーネントの内部レイアウト

この使い分けにより、より保守性の高いCSSアーキテクチャを構築できます。

/* 従来のメディアクエリ(ビューポート基準) */
@media (max-width: 768px) {
  .cards {
    flex-direction: column;
  }
}

/* コンテナクエリ(親要素基準) */
@container (max-width: 300px) {
  .cards {
    flex-direction: column;
  }
}

基本的な使用方法

1. コンテナの定義

まず、コンテナクエリを使用したい要素の親要素を「クエリコンテナ」として定義します。

.container {
  container-type: inline-size; /* 幅に基づくクエリを有効化 */
}

/* または */
.container {
  container-type: size; /* 幅と高さの両方に基づくクエリを有効化 */
}

container-typeの値

  • inline-size: 幅のみを監視(最も一般的)
  • size: 幅と高さの両方を監視
  • normal: コンテナクエリを無効化(デフォルト)

2. コンテナクエリの記述

定義したコンテナのサイズに基づいてスタイルを適用します。

.cards {
  display: flex;
  gap: 1rem;
}

@container (max-width: 400px) {
  .cards {
    flex-direction: column;
  }

  .cards__image {
    width: 100%;
  }
}

@container (min-width: 600px) {
  .cards {
    padding: 2rem;
  }

  .cards__title {
    font-size: 2rem;
  }
}

3. 名前付きコンテナ

複数のコンテナを使用する場合は、名前を付けて区別できます。これにより、どのコンテナに対するクエリなのかを明確に指定できます。

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

.main-content {
  container-type: inline-size;
  container-name: main;
}

/* 特定のコンテナに対するクエリ */
@container sidebar (max-width: 250px) {
  .widget {
    /* サイドバーが狭い時のスタイル */
    font-size: 0.875rem;
    padding: 0.5rem;
  }
}

@container main (min-width: 800px) {
  .article {
    /* メインコンテンツが広い時のスタイル */
    columns: 2;
    column-gap: 2rem;
  }
}

ショートハンド記法

.container {
  container: sidebar / inline-size; /* 名前 / タイプ */
}

実用例:レスポンシブカードコンポーネント

以下は、コンテナのサイズに応じてレイアウトが変化するカードコンポーネントの例です。

/* カードコンテナの定義 */
.card-container {
  container-type: inline-size;
  container-name: card;
}

.card {
  display: grid;
  gap: 1rem;
  padding: 1rem;
  border: 1px solid #e0e0e0;
  border-radius: 8px;
  background: white;
}

/* 狭いコンテナ:縦並びレイアウト */
@container card (max-width: 350px) {
  .card {
    grid-template-columns: 1fr;
    text-align: center;
  }

  .card__image {
    width: 100%;
    max-width: 200px;
    margin: 0 auto;
  }

  .card__title {
    font-size: 1.25rem;
  }
}

/* 中サイズのコンテナ:画像とコンテンツを横並び */
@container card (min-width: 351px) and (max-width: 599px) {
  .card {
    grid-template-columns: 120px 1fr;
    align-items: start;
  }

  .card__title {
    font-size: 1.125rem;
  }
}

/* 広いコンテナ:ゆったりとしたレイアウト */
@container card (min-width: 600px) {
  .card {
    grid-template-columns: 200px 1fr;
    align-items: center;
    padding: 2rem;
  }

  .card__content {
    padding-left: 1.5rem;
  }

  .card__title {
    font-size: 1.5rem;
    margin-bottom: 0.75rem;
  }
}

このように、同じカードコンポーネントを異なるサイズのコンテナに配置しても、常に最適なレイアウトが適用されます。

ブラウザサポート

対応状況

コンテナクエリは比較的新しい機能ですが、主要なモダンブラウザで広くサポートされています:

  • Chrome: 105+ (2022年8月〜)
  • Firefox: 110+ (2023年2月〜)
  • Safari: 16.0+ (2022年9月〜)
  • Edge: 105+ (2022年9月〜)

詳細な対応状況:Can I use: CSS Container Queries

参考リンク