CSS コンテナ クエリ: 真にレスポンシブなコンポーネント
長年にわたり、レスポンシブ デザインとは、「レイアウトをビューポートに適応させる」ことを意味していました。
コンポーネントカードには、 @media (max-width: 768px) 彼はそれがどれほど広いかを知っています
画面は表示されますが、実際にどのくらいのスペースが利用できるのかはわかりません。
コンテキスト。そのカードを狭いサイドバーに配置すると、次のように動作します。
モバイルでは、たとえ画面が 27 インチのデスクトップであっても。メインコンテンツに入れてください。
コンテナがスマートフォンより狭い場合でも、デスクトップのように動作します。
Le CSSコンテナクエリ この問題を根本から解決します。 コンポーネントはサイズに反応する可能性があります。 自分のコンテナではありません ビューポートの。優れたブラウザサポート2025 年のベースラインでは 88% (Chrome 105 以降、Firefox 110 以降、Safari 16 以降)、この手法は実稼働環境に対応しています。
何を学ぶか
- メディア クエリとコンテナ クエリの基本的な違い
- 包含コンテキストを定義する方法
container-type - 構文
@containerクエリ用 - コンテナー サイズのクエリ: インライン サイズ、ブロック サイズ
- コンテナ スタイル クエリ: カスタム プロパティに基づくクエリ
- 階層クエリ用の名前付きコンテナ
- コンテナクエリをAngular、React、Vueに統合する方法
メディアクエリの問題
メディア クエリは、メディアの特性をクエリします。 ビューポート: 幅 画面の向き、向き、配色。これは、レイアウトと シンプルであり、コンポーネントは常に予測可能な幅を占めます。しかしデザインにおいては 最新のシステムでは、同じコンポーネントが根本的に異なるコンテキストで再利用されます。
- ホームページ上の製品カード (デスクトップ上に 3 列)
- 「関連商品」サイドバーの同じカード(狭い 1 列)
- 全画面モーダルの同じカード (2 列)
- 検索ページ上の同じカード (アクティブなフィルターに基づいて変数)
メディアクエリでは、それぞれの使用法のコンテキストを事前に把握し、記述する必要があります。 ケース固有の CSS セレクター。コンテナクエリでは、e 自律型: 利用可能なスペースに自動的に適応します。
コンテナを定義する
コンテナクエリを使用するには、最初のステップは、どの要素がコンテナクエリであるかを宣言することです。
問われる「器」。財産を使って行われます container-type:
/* Crea un container che risponde alla larghezza (inline-size) */
.card-wrapper {
container-type: inline-size;
}
/* Crea un container che risponde sia a larghezza che altezza */
.card-wrapper {
container-type: size;
}
/* Dai un nome al container per query gerarchiche */
.card-wrapper {
container-type: inline-size;
container-name: card;
}
/* Shorthand */
.card-wrapper {
container: card / inline-size;
}
アイテムが取得されると、 container-type、彼の子孫全員
彼らは使える @container 寸法を照会します。
構文 @container
構文はメディア クエリと同じですが、ビューポートをクエリする代わりに、 包含コンテキストを使用して最も近いコンテナをクエリします。
.card {
/* Layout default: verticale, compatto */
display: grid;
grid-template-areas:
"image"
"content";
gap: 12px;
}
.card__image {
aspect-ratio: 16 / 9;
object-fit: cover;
border-radius: 8px 8px 0 0;
}
/* Quando il container e largo almeno 400px: layout orizzontale */
@container (min-width: 400px) {
.card {
grid-template-areas: "image content";
grid-template-columns: 200px 1fr;
}
.card__image {
aspect-ratio: 1;
border-radius: 8px 0 0 8px;
}
}
/* Quando il container e largo almeno 600px: layout espanso */
@container (min-width: 600px) {
.card {
grid-template-columns: 280px 1fr;
gap: 24px;
padding: 24px;
}
.card__title {
font-size: 1.5rem;
}
}
/* Range syntax (CSS Level 4) - piu leggibile */
@container (200px <= width <= 400px) {
.card {
/* stile per range specifico */
}
}
名前付きコンテナ: 階層クエリ
ネストされたコンテナがある場合、クエリを実行するコンテナに名前を付けることができます。 最も近い祖先ではなく特定の祖先:
<!-- HTML struttura -->
<main class="layout" style="container: layout / inline-size">
<aside class="sidebar" style="container: sidebar / inline-size">
<div class="widget">
<!-- Questo widget puo interrogare sia "sidebar" che "layout" -->
</div>
</aside>
</main>
/* Query sul container "sidebar" (il piu vicino) */
@container sidebar (min-width: 300px) {
.widget { display: flex; }
}
/* Query sul container "layout" (l'antenato nominato) */
@container layout (min-width: 1200px) {
.widget { max-width: 400px; }
}
コンテナ スタイル クエリ: 隠れた機能
サイズ クエリに加えて、コンテナ クエリもサポートされています。 スタイル クエリ: コンテナの CSS カスタム プロパティの値に基づいてクエリを実行します。 この機能は Chrome 111 以降および Safari 17.4 以降でサポートされており、可能性を広げます。 テーマとコンポーネントのバリエーションの点でまったく新しいものです。
/* Definisci una custom property sul container */
.card-wrapper {
container-type: style;
/* La variante del componente viene comunicata via custom property */
--card-variant: featured;
}
/* Il componente si adatta alla variante del container */
@container style(--card-variant: featured) {
.card {
border: 2px solid var(--color-accent);
background: var(--color-accent-subtle);
}
.card__badge {
display: block; /* mostra il badge "In evidenza" */
}
}
@container style(--card-variant: compact) {
.card {
padding: 8px;
font-size: 0.875rem;
}
.card__image {
display: none; /* nasconde l'immagine in modalita compatta */
}
}
このパターンを使用すると、セマンティック コンテキストをコンテナからコンテナに伝達できます。 追加の CSS クラスや JavaScript クラスを必要とせず、カプセル化を維持するコンポーネント。
コンテナ測定単位: cqw、cqh、cqi、cqb
コンテナ クエリでは、コンテナに関連する新しい測定単位も追加されます。
cqw: コンテナの幅の 1%cqh: 容器の高さの 1%cqi: コンテナのインライン サイズの 1% (= LTR レイアウトの場合は cqw)cqb: コンテナブロックサイズ (= cqh) の 1%cqmin: cqi と cqb の小さい方cqmax: cqi と cqb の大きい方
/* Tipografia fluida relativa al container */
.card__title {
/* Scala da 16px a 24px in base alla larghezza del container */
font-size: clamp(1rem, 4cqi, 1.5rem);
}
/* Padding proporzionale al container */
.card {
padding: 5cqi;
}
/* Gap che si adatta */
.card__grid {
display: grid;
gap: clamp(8px, 2cqi, 24px);
}
Angular、React、Vue のコンテナ クエリ
Angular: コンテナ対応コンポーネント
/* card.component.scss */
:host {
display: block;
container-type: inline-size;
container-name: card-host;
}
.card {
display: grid;
grid-template-areas: "image" "content";
gap: 12px;
}
@container card-host (min-width: 400px) {
.card {
grid-template-areas: "image content";
grid-template-columns: 180px 1fr;
}
}
// card.component.ts
@Component({
selector: 'app-card',
templateUrl: './card.component.html',
styleUrls: ['./card.component.scss'],
// :host come container - nessun JS necessario per il responsive
host: { class: 'card-container' }
})
export class CardComponent {
@Input() product!: Product;
}
React: コンテナ クエリを備えた CSS モジュール
/* card.module.css */
.wrapper {
container-type: inline-size;
container-name: card;
}
.card {
display: grid;
gap: 12px;
}
@container card (min-width: 400px) {
.card {
grid-template-columns: 180px 1fr;
}
}
// Card.tsx
import styles from './card.module.css';
export function Card({ product }: { product: Product }) {
return (
<div className={styles.wrapper}>
<article className={styles.card}>
<img src={product.image} alt={product.name} />
<div>
<h3>{product.name}</h3>
<p>{product.description}</p>
</div>
</article>
</div>
);
}
コンテナ クエリとメディア クエリ: いつ何を使用するか
| シナリオ | 最適な選択 | 理由 |
|---|---|---|
| グローバルページレイアウト | メディアクエリ | レイアウトはビューポートに依存します |
| 再利用可能なコンポーネント | コンテナクエリ | コンポーネントはそのコンテキストに適応する必要があります |
| デザインシステムトークン | 両方 | ブレークポイントのビューポート、バリアントのコンテナ |
| ダーク/ライトモード | メディアクエリ | カラースキームとメディア機能を好みます |
| 動的なサイドバー | コンテナクエリ | コンテンツは開いた/閉じたサイドバーに収まります |
| プリントスタイリング | メディアクエリ | @media print はメディア クエリです |
パターンアンチ: コンテナクエリでよくある間違い
間違い #1: コンテナ自体がクエリを実行する
要素 container-type 彼は自分自身に疑問を抱くことができない
@container — 変更された子孫である必要があります。
コンテナとルールを定義しないでください @container 同じ上に
セレクター。
エラー#2: コンテナタイプ: 高さが定義されていないサイズ
container-type: size コンテナにはサイズが必要です
幅と高さの両方で定義されます。使用する場合 size コンテナの上に
明示的な高さのないクエリ height e cqh
期待どおりに機能しません。アメリカ合衆国 inline-size 大多数で
ケースの。
次のステップ
コンテナー クエリのおかげで、真に応答性の高いコンポーネントが得られました。 シリーズの次の記事では、CSS Anchor Positioning API について説明します。 JavaScript を 1 行も使用せずにツールチップ、ドロップダウン、ポップオーバーを実装するには: 開発者が待ち望んでいた宣言機能に CSS を近づけるもう 1 つのテクニック 何年も。
結論
CSS コンテナ クエリは構築方法を根本的に変えます 応答性の高いコンポーネント。グローバル ブレークポイント システムの代わりに、各コンポーネントが を理解し、尊重する必要があり、各コンポーネントは自律し、それぞれのコンポーネントに適応します。 コンテキスト。これにより、より保守しやすいコード、真に構成可能な設計システムが実現します。 手動で管理する必要があるエッジケースも少なくなります。
ブラウザーのサポート率が 88% を超えているため、コンテナー クエリをデプロイする準備ができています 今日の製作。を開始してコンポーネントを特定するための最良の方法 複数のコンテキストで使用されるデザイン システム (通常はカード、リスト項目、 メディア オブジェクト — そしてそれらを新しいパラダイムに徐々に変換します。







