CSS Container Queriesでコンポーネント単位のレスポンシブデザインを実現する

問題

カードコンポーネントをmedia queryでレスポンシブ対応していましたが、同じコンポーネントをサイドバーに配置するとレイアウトが崩れてしまいます。media queryはビューポート基準のため、コンポーネントの実際の表示領域に対応できないのが原因です。

解決方法

CSS Container Queriesを使えば、ビューポートではなく親コンテナのサイズを基準にスタイルを適用できます。

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

/* コンテナの幅に基づいてレスポンシブを適用 */
.card {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1rem;
}

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

@container card (min-width: 700px) {
  .card {
    grid-template-columns: 300px 1fr;
    font-size: 1.1rem;
  }
}

これにより、.cardコンポーネントはサイドバーでもメインエリアでも、親コンテナのサイズに応じて自動的にレイアウトが変わります。

container-typeには3つの値があります:

container-type: inline-size;  /* 横幅のみ追跡(最も一般的) */
container-type: size;         /* 横幅+高さを追跡 */
container-type: normal;       /* デフォルト、クエリ対象外 */

省略記法もあります:

/* container-name + container-type を一括指定 */
.wrapper {
  container: card / inline-size;
}

ポイント

  • @containerはビューポートではなく親コンテナのサイズ基準なので、再利用可能なコンポーネントに最適です
  • ブラウザサポート率は95%以上(Chrome 105+、Firefox 110+、Safari 16+)で、本番環境でも安心して使えます
  • container-type: inline-sizeが最も実用的で、sizeは高さベースのクエリが必要な特殊なケースでのみ使用します