恥ずかしながらCSSのコンテナクエリを知らなかったので調べてみた
本記事のサマリ
先日Xでコンテナクエリという言葉を見かけて「何それ?」となった私が、調べてみたらこれがかなり便利そうだったので共有します。CSSコンテナクエリは「画面サイズ」ではなく「親要素のサイズ」に基づいてスタイルを切り替える仕組みで、2022年後半から主要ブラウザで実装されていました。知らなかった...というより、気づいたら使える状態になっていた、というのが正直なところです。
これまでレスポンシブデザインといえば、メディアクエリで「画面幅が768px以下なら...」「1024px以上なら...」といった具合に、ビューポート(画面全体)のサイズを基準にスタイルを切り替えるのが当たり前でした。しかし実際の制作現場では、同じコンポーネントがサイドバーに入る場合とメインコンテンツに入る場合で、全く違うレイアウトが必要になることがよくあります。
コンテナクエリは、この問題を根本的に解決します。「このコンポーネントを包む親要素の幅が300px以下なら縦並び、600px以上なら横並び」といったように、コンポーネント自身が置かれた環境に応じて柔軟に変化できるようになったのです!
メディアクエリとの根本的な違い
従来のメディアクエリとコンテナクエリの違いを整理してみると、その設計思想の違いが見えてきます。
メディアクエリは「外から内へ」のアプローチです。画面全体のサイズを見て、その条件に基づいてレイアウト全体を調整します。これは確かに強力な仕組みですが、モジュール化や再利用という観点では限界がありました。
一方でコンテナクエリは「内から内へ」のアプローチと言えます!各コンポーネントが自分の置かれた環境(親要素のサイズ)を判断して、自律的にレイアウトを調整します。これにより、同じコンポーネントがどんな場所に配置されても適切に表示されるようになります。
例えば、カードコンポーネントを考えてみてください。従来の手法では「画面幅が小さい時は全てのカードを縦並びに」といった大雑把な制御しかできませんでした。しかしコンテナクエリなら「このカードの幅が狭い時は画像を上に、広い時は横に配置」といった、より細やかで的確な制御が可能になります。
実際の使い方と設計思想の変化
コンテナクエリを使う際の基本的な流れは意外とシンプルです。まず、コンテナとなる要素に container-type を指定します。
.card-container {
container-type: inline-size;
container-name: card;
}
そして、その中の子要素に対して @container ルールでスタイルを定義します。
@container card (min-width: 400px) {
.card-content {
display: flex;
flex-direction: row;
}
}
@container card (max-width: 399px) {
.card-content {
display: flex;
flex-direction: column;
}
}
ここで重要なのは、設計思想の変化です。これまでは「画面サイズに応じてレイアウト全体を調整する」という上から下への発想でしたが、コンテナクエリでは「各コンポーネントが自分の環境に応じて最適化する」という分散的な発想になります。
この変化は、コンポーネント指向の開発手法とも非常に相性が良いです。ReactやVueなどで再利用可能なコンポーネントを作る際に、そのコンポーネントがどこで使われても適切に表示されるような自己完結性を持たせることができます。
新しい長さ単位も導入されています。cqw(コンテナ幅の1%)、cqh(コンテナ高さの1%)、cqi(コンテナのインライン方向サイズの1%)などを使うことで、より細かい制御が可能になっています。
LP制作・アニメーション実装での活用シーン
LP(ランディングページ)制作やアニメーション実装の現場で、コンテナクエリはどのような価値を発揮するでしょうか。
まず、多言語対応での威力は相当なものです。日本語、英語、ドイツ語など、言語によってテキストの長さが大きく変わる際に、従来は「最も長い言語を基準にレイアウトを組む」か「言語ごとに個別のCSSを用意する」といった対応が必要でした。
コンテナクエリを使えば、テキストの長さによってコンテナのサイズが変わった時に、自動的にレイアウトが最適化されます。長い文言の時は縦積み、短い文言の時は横並びといった切り替えが、言語を意識せずに実現できるのです!
アニメーション制御の面でも面白い可能性が...
これまでJavaScriptで「画面幅に応じてアニメーションパターンを切り替える」処理を書いていた部分を、CSS側でより宣言的に表現できるようになります。
例えば、ヒーロー領域のアニメーションで「コンテナが狭い時はフェードイン、広い時はスライドイン」といった制御をCSS単体で実現できるようになると、メンテナンス性が格段に向上します。JavaScriptは「いつアニメーションを開始するか」の制御に専念し、「どんなアニメーションにするか」の判断はCSSに委ねる、といった役割分担が明確になりますね。
ブラウザサポートと注意点
現在のブラウザサポート状況は比較的良好です。主要ブラウザでの正式リリースは以下のタイミングでした:
- Chrome 105(2022年8月30日)
- Safari 16(2022年9月12日)
- Firefox 110(2023年2月14日)
2022年後半から2023年初頭にかけて一気に実装が進んだ形です。つまり、現時点では2年以上前からサポートされている機能ということになりますね。
ただし、実務で導入する際にはいくつかの注意点があります。
まず、レガシーブラウザ対応です。サポートされていない環境でのフォールバック戦略を事前に考えておく必要があります。@supports を使った条件分岐で、対応ブラウザでは新しい手法、非対応ブラウザでは従来のメディアクエリを使う、といったアプローチが現実的でしょう。
@supports (container-type: inline-size) {
/* コンテナクエリを使った実装 */
}
@supports not (container-type: inline-size) {
/* 従来のメディアクエリでのフォールバック */
}
また、設計時の考慮事項として「無限ループ」の可能性があります。コンテナクエリでフォントサイズを変更し、それによってテキストの折り返しが変わり、コンテナのサイズが変わって、また別の条件が適用される...といった循環を避ける必要があります。
設計思想の変化への対応も重要です。これまでの「画面幅基準」の発想から「コンテナサイズ基準」の発想への切り替えには、チーム全体での理解共有が欠かせません。特に、「このコンポーネントはどんな親要素に配置される可能性があるか」を事前に整理しておくことが、安定したレイアウト設計につながります。
まとめ
恥ずかしながら知らなかったCSSコンテナクエリですが、調べてみたら想像以上に実用的な機能でした。従来の画面サイズ基準から親要素サイズ基準への転換により、より柔軟で再利用可能なコンポーネント設計が実現できるようになっています。
特にLP制作や多言語対応、アニメーション制御といった実務の現場では、その恩恵を強く感じられそうです。ブラウザサポートも2022年後半から進んでおり、既に2年以上が経過しています。フォールバック戦略を用意すれば、実践投入も十分可能な段階に来ているようです。
ただし、新しい技術には新しい落とし穴もあります。設計思想の変化を理解し、チーム全体で知識を共有しながら、段階的に導入していくのが良さそうです。まずは小さなコンポーネントから試してみて、徐々に適用範囲を広げていく。そんなアプローチで、私も次世代のレスポンシブデザインに踏み出してみようと思います👍
株式会社StellarCreate(stellar-create.co.jp)のエンジニアブログです。 プロダクト指向のフルスタックエンジニアを目指す方募集中です! カジュアル面談で気軽に雑談しましょう!→ recruit.stellar-create.co.jp/
Discussion