コンテナクエリ

@containercontainer-typecontainer-namecqwcqhcqicqb

コンテナクエリは、ビューポートではなく親コンテナ要素のサイズに応じてスタイルを変えられます。コンポーネントベース開発に革命をもたらした2023年の最重要CSS機能です。

デモ:コンテナ幅でレイアウトが変わるカード

コンテナ幅: 約250px(縦積みレイアウト)

🎨
デザインシステム
コンポーネントが自分のコンテナに応じてレイアウトを変えます

コンテナ幅: 約450px(横並びレイアウト)

🎨
デザインシステム
コンポーネントが自分のコンテナに応じてレイアウトを変えます

コンテナ幅: 100%(大きいテキスト + 広いレイアウト)

🎨
デザインシステム
コンポーネントが自分のコンテナに応じてレイアウトを変えます。同じHTMLで3種類のレイアウト!

デモ:右端をドラッグしてリサイズ(ブラウザ対応時)

← 右端ドラッグでリサイズ可能

🛍️
プレミアム商品
¥4,980

幅 <280px: 縦積み / 280px〜: 横並び / 380px〜: ボタン表示

デモ:container-name(名前付きコンテナ)

サイドバー(狭い)

コンテンツウィジェット

メインエリア(広い)

コンテンツウィジェット

同じコンポーネントがサイドバーとメインで違うスタイルを適用します

コード例

/* ① コンテナを定義 */
.card-wrapper {
  container-type: inline-size; /* 幅に応じて変化(最もよく使う) */
  /* container-type: size;         幅と高さ両方 */
  /* container-type: normal;       クエリ対象にしない(デフォルト) */
}

/* 名前付きコンテナ */
.sidebar {
  container-type: inline-size;
  container-name: sidebar;    /* 名前をつける */
}

/* shorthand */
.wrapper {
  container: card-layout / inline-size; /* name / type */
}

/* ② コンテナクエリの記述 */
@container (width >= 400px) {
  .card { flex-direction: row; }
}

/* 名前付きコンテナへのクエリ */
@container sidebar (width < 250px) {
  .widget { display: none; }
}

/* 範囲指定 */
@container (200px <= width <= 600px) {
  .card { grid-template-columns: 1fr 1fr; }
}

/* ③ コンテナクエリ単位 */
.card-title {
  font-size: 5cqw;   /* コンテナ幅の5% */
  padding: 2cqh;     /* コンテナ高さの2% */
  margin: 1cqi;      /* インラインサイズの1% */
}
/* cqw / cqh / cqi / cqb / cqmin / cqmax */

比較:@container vs @media

観点@container(コンテナクエリ)@media(メディアクエリ)
基準親コンテナ要素のサイズビューポート(ブラウザウィンドウ)のサイズ
適用範囲コンポーネント単位で独立ページ全体のレイアウト
再利用性✅ どこに置いても自動適応(真の再利用可能コンポーネント)❌ 配置場所が変わると壊れる可能性
コンポーネント設計✅ 最適(コンポーネントが自律的)❌ グローバルな前提が必要
典型的な用途カード・ウィジェット・サイドバーの内部レイアウトページ全体のカラム数、ナビゲーションの切り替え
ブラウザサポートChrome 105+ / Firefox 110+ / Safari 16+全ブラウザ対応(15年以上前から)
パフォーマンスほぼ同等(ブラウザ最適化済み)同等

NEWコンテナクエリ — コンポーネント設計に革命(2023)

コンテナクエリは CSS の10年来の課題を解決しました。以前は「このカードをサイドバーに置いたらメインエリアに置いた時と違うスタイルにしたい」という要求をCSSだけで実現できませんでした。 JavaScriptや複雑なクラス管理が必要でしたが、コンテナクエリによりコンポーネント自身が自分のサイズに適応できるようになりました。

コンテナクエリが解決する問題の例

❌ @media だけでは困難だったこと
  • サイドバー内のカードを横並びにしたい
  • 3カラム→1カラムに変わった時のカード内レイアウト
  • 再利用可能なコンポーネントライブラリ
  • 配置場所に依存しないウィジェット
✅ @container で解決できること
  • コンテナが狭ければ縦、広ければ横
  • どこに配置しても自動適応
  • ビューポートに一切依存しないコンポーネント
  • CSSだけで完結(JS不要)
/* 完全な実装例: どこに置いても適応するカードコンポーネント */

/* ラッパーにコンテナを設定(JSXでの使用例) */
/* <div style={{ containerType: 'inline-size' }}> */
/*   <ProductCard />                               */
/* </div>                                          */

/* カードのデフォルト: 縦積み(狭い環境) */
.product-card {
  display: grid;
  grid-template-columns: 1fr;
  gap: 12px;
}

/* 300px以上: 画像を横に */
@container (width >= 300px) {
  .product-card {
    grid-template-columns: 100px 1fr;
    align-items: center;
  }
}

/* 500px以上: さらに詳細情報を表示 */
@container (width >= 500px) {
  .product-card { grid-template-columns: 160px 1fr auto; }
  .product-extra-info { display: block; }
  .product-actions { flex-direction: row; }
}

Chrome 105+(2022年8月), Firefox 110+(2023年2月), Safari 16+(2022年9月)でサポート。 2024年現在、全主要ブラウザで利用可能です。積極的に採用しましょう!

🤖 AIプロンプトテンプレート

CSSコンテナクエリ(@container)を使ったコンポーネントベースのレスポンシブデザインをReact + Tailwind CSSで実装してください。

要件:
- container-type: inline-size を使った基本的な@containerの使い方
- コンテナ幅に応じてカードのレイアウトが縦並び→横並びに切り替わるデモ
- container-name を使った名前付きコンテナクエリ
- メディアクエリとの違い(コンポーネント単体でレスポンシブになる利点)を説明
- resizableな親コンテナを用意してリアルタイムでレイアウト変化を確認できるデモ
- コンテナクエリの単位(cqi / cqb / cqw / cqh)の説明と使用例

コンテナサイズに応じて変化するコンポーネントを視覚的に確認できるデモにしてください。

⚠️ このプロンプトはあくまでたたき台です。AIの回答はモデルやバージョン、会話の文脈によって毎回異なります。意図通りに動かない場合は、条件を追記・修正してお使いください。