フロントエンド開発者として10年以上CSSと向き合ってきた中で、レスポンシブデザインは常に課題の中心にあった。従来のメディアクエリはビューポート幅を基準にスタイルを切り替える仕組みだが、コンポーネントベースの開発が主流となった現在、この仕組みには根本的な問題がある。
例えば、カードコンポーネントを考えてほしい。サイドバーに配置した場合と、メインコンテンツに配置した場合では、同じビューポート幅でも利用可能な領域が全く異なる。メディアクエリではビューポート全体の幅しか参照できないため、コンポーネントの実際の描画領域に応じたスタイル変更が非常に困難だった。
CSS Container Queriesは、この長年の課題を根本から解決する仕様だ。親要素のサイズに基づいてスタイルを切り替えることで、真にコンポーネントベースのレスポンシブデザインが実現できる。
Container Queriesを使うには、まずコンテナとなる要素を宣言する必要がある。これはcontainer-typeプロパティで行う。
/* コンテナの宣言 */
.card-wrapper {
container-type: inline-size;
container-name: card;
}
/* コンテナクエリによるスタイル変更 */
@container card (min-width: 400px) {
.card {
display: grid;
grid-template-columns: 200px 1fr;
gap: 1rem;
}
}
@container card (max-width: 399px) {
.card {
display: flex;
flex-direction: column;
}
}
container-typeにはinline-size、size、normalの3つの値がある。実務ではinline-sizeを使うケースが圧倒的に多い。
実際のプロジェクトで最も効果を感じたのは、管理画面のダッシュボード開発だ。KPIカード、グラフ、テーブルなど様々なウィジェットが配置され、ユーザーがレイアウトをカスタマイズできる仕様だった。
<div class="dashboard-grid">
<div class="widget-container" style="grid-column: span 2;">
<div class="kpi-card">
<span class="kpi-value">1,234</span>
<span class="kpi-label">月間アクティブユーザー</span>
<div class="kpi-chart">...</div>
</div>
</div>
</div>
.widget-container {
container-type: inline-size;
container-name: widget;
}
/* 狭い領域:数値とラベルのみ表示 */
@container widget (max-width: 250px) {
.kpi-card .kpi-chart {
display: none;
}
.kpi-card .kpi-value {
font-size: 1.5rem;
}
}
/* 中程度の領域:横並び表示 */
@container widget (min-width: 251px) and (max-width: 500px) {
.kpi-card {
display: flex;
align-items: center;
gap: 1rem;
}
}
/* 広い領域:フル表示 */
@container widget (min-width: 501px) {
.kpi-card {
display: grid;
grid-template-columns: 1fr 2fr;
grid-template-rows: auto 1fr;
}
}
この実装により、ウィジェットの配置サイズに応じて自動的に最適なレイアウトが適用される。メディアクエリでこれを実現しようとすると、配置パターンごとにクラスを切り替えるJavaScriptが必要だった。
Container Queriesとあわせて導入されたContainer Query Unitsも非常に便利だ。cqw(コンテナ幅の1%)やcqh(コンテナ高さの1%)を使うことで、コンテナサイズに比例したスタイリングが可能になる。
@container widget (min-width: 300px) {
.kpi-value {
font-size: clamp(1.2rem, 5cqw, 3rem);
}
.kpi-card {
padding: 2cqw;
}
}
この手法は特にタイポグラフィの調整で威力を発揮する。ビューポート単位のvwでは意図しないサイズになりがちだったが、cqwを使えばコンテナに最適化されたサイズ設定が可能だ。
Container Queriesを既存プロジェクトに導入する際は、段階的なアプローチを推奨する。まずは再利用頻度の高いコンポーネントから始めるのが効果的だ。
筆者のチームでは以下の手順で移行を進めた。
/* フォールバック付きの実装 */
.card {
display: flex;
flex-direction: column;
}
/* メディアクエリによるフォールバック */
@media (min-width: 768px) {
.main-content .card {
flex-direction: row;
}
}
/* Container Queriesによる本命の実装 */
@supports (container-type: inline-size) {
.card-wrapper {
container-type: inline-size;
}
@container (min-width: 400px) {
.card {
flex-direction: row;
}
}
}
Container Queriesはブラウザのレイアウト計算に影響を与えるため、パフォーマンスへの配慮が必要だ。container-type: inline-sizeを指定すると、その要素にはCSS Containmentが適用される。これは通常パフォーマンスに好影響だが、overflowの挙動が変わる場合がある点に注意が必要だ。
また、深くネストされたコンテナクエリは避けるべきだ。コンテナの中にコンテナを何層も入れると、レイアウト計算のコストが増加する。実務では2〜3層程度に抑えるのが適切だろう。
CSS Container Queriesは、CSSにおけるレスポンシブデザインのパラダイムを根本から変える仕様だ。ビューポートからコンテナへと基準点が移ることで、コンポーネントの再利用性が飛躍的に向上する。デザインシステムの構築やUIライブラリの開発において、今後必須の技術となるだろう。既存プロジェクトでも段階的な導入は十分可能なので、ぜひ小さなコンポーネントから試してみてほしい。