Skip to content

コンテナクエリが知られているのに使われない理由

CSSのコンテナクエリ(container queries)が主要ブラウザにそろってから、それなりの時間がたちました。部品が置かれた場所の広さに合わせて見た目を変えたい、という要望は長年のCSSの願いごとの上位にあったはずです。ところが、実際の制作現場ではまだあまり使われていません。

Smashing Magazineが9月16日に公開した記事は、この「知られているのに使われない」状態を正面から取り上げています。筆者は、使われない理由よりも、使われたときの使い方のずれに関心を向けています。今回はこの記事を軸に、MDNの解説も参照しながら、メディアクエリとの役割分担や、手を出す前に知っておきたい落とし穴を整理してみます。

認知は高いのに利用が伸びていない

記事によると、コンテナクエリのブラウザ対応率はおよそ94%に達しています。一方で、State of CSSの調査では、存在を知っている開発者が86%なのに対し、実際に使っているのは41.4%にとどまるそうです。筆者自身も調査には偏りがあると断ったうえで、現時点で最も参考になる指標だとしています。

また、今年のSmashingConf Amsterdamでは、CSSの解説で知られるKevin Powell氏も普及の遅さに触れたと紹介されています。新機能というより、すでに使える道具が棚に置かれたままになっている状況といえます。

筆者が指摘するのは、コンテナクエリが見た目のうえでメディアクエリとよく似ていることです。書き方が似ているので、同じ目的で同じように動くものだと思い込みやすい。その結果、メディアクエリの置き換えとして試し、違いが分からないまま離れていく、という流れが起きやすいのだと考えられます。

外を見るメディアクエリ、内を見るコンテナクエリ

記事の整理はシンプルです。メディアクエリが確かめているのは、基本的に画面(ビューポート)の幅です。たとえば幅1024px以上でカードを横並びにする指定をしたとします。このカードを、1920pxの画面の中で幅300pxしかないグリッドの一枠に置いても、画面幅の条件は満たしているので横並びの指定が効いてしまい、中身が窮屈になったりはみ出したりします。

コンテナクエリは問いの立て方が違います。確かめるのは、その部品を包んでいる親要素にどれだけの幅があるかです。次のように親要素をコンテナとして宣言し、その幅を条件にします。

.card-wrapper {
  container-name: card;
  container-type: inline-size;
}

@container card (min-width: 450px) {
  .card {
    display: flex;
    flex-direction: row;
  }
}

こうするとカードは画面の広さに左右されず、置かれた場所に450px以上の横幅があるときだけ横並びになります。MDNも、コンテナクエリを使えば、同じカードをページのどこに置くかを意識せずに再利用できると説明しています。

記事は、現在のウェブには2,300種類を超える画面サイズがあるという数字も挙げています。768pxのような抽象的な境目を越えたから「タブレット用」の見た目になる、という考え方そのものに無理が出てきている、というのが筆者の主張です。

ページ全体の骨組みと部品の中身で使い分ける

記事が勧めるのは、どちらか一方に寄せることではなく、担当範囲を分けることです。ページ全体をまたぐヘッダーやフッター、メインのグリッド、ダークモードのような利用者の設定、タッチ操作の有無といった端末の特性は、これまでどおりメディアクエリの担当です。一方、カードやウィジェット、フォーム、ナビゲーションのように、割り当てられた場所に収まる必要がある部品の中身は、コンテナクエリの担当と考えます。

筆者自身の判断基準も分かりやすいものです。ひとつの部品が複数の場所で使われるならコンテナクエリ、ページの最上部に常にあるメインナビゲーションのように、ページ単位でしか存在しない部品ならメディアクエリ。前者は置き場所の広さが毎回違い、後者は画面の幅がそのまま頼れる目安になるからです。

WordPressで制作していると、この区別は実感しやすいはずです。同じ投稿カードや問い合わせボタンの部品が、トップページでは3列に並び、固定ページでは本文の幅いっぱいに置かれ、別の場所ではサイドバーに収まる。画面幅だけで分岐を書いていると、置き場所ごとに例外の指定が増えていきます。納品後に更新担当の方がブロックを並べ替えることを考えても、部品が自分の置かれた幅に応じて整う作りのほうが崩れにくくなります。

文字サイズと折り返しの判定にも使える

記事では、レイアウトの切り替え以外の使いどころも紹介されています。ひとつは文字サイズです。見出しの大きさを画面幅に連動するvw単位とclamp()で決めていると、その部品をサイドバーへ移したときに文字が大きすぎたり小さすぎたりします。コンテナクエリには専用の単位があり、MDNによると、cqwとcqhはコンテナの幅と高さ、cqiとcqbは行方向とブロック方向の大きさ、それぞれの1%を表します。cqminとcqmaxはcqiとcqbの小さいほうと大きいほうです。

.card-title {
  font-size: clamp(1rem, .5rem + 3cqi, 2rem);
}

このように書けば、見出しの大きさは部品が置かれた場所の幅に合わせて伸び縮みし、指定がその部品の中で完結します。なお、MDNでは、当てはまるコンテナが見つからない場合、これらの単位はその方向の小さいビューポート単位として扱われると説明されています。

もうひとつは、フレックスボックスの折り返しを検知する工夫です。CSSには、並んだ要素が次の行へ折り返したかどうかを直接知る仕組みがありません。記事ではKevin Powell氏から学んだ方法として、各アイテム自体をコンテナにし、伸びる設定を与えておくやり方が紹介されています。折り返しが起きると、次の行に落ちたアイテムが親の幅いっぱいまで広がり、その急な幅の変化をコンテナクエリが拾う、という仕組みです。これまでならJavaScriptのResizeObserverに頼っていた場面を、CSSだけで扱える可能性があります。筆者も完全無欠ではないと書いているので、試すときは実際の表示で確かめるのがよさそうです。

手を出す前に知っておきたい落とし穴

記事は、コンテナクエリ特有の注意点も3つ挙げています。

まず、コンテナは自分自身を条件にできない点です。カード要素をコンテナにして、そのカード自身の表示方法を切り替えようとしても動きません。自分の大きさで自分の見た目を変えると、無限に計算し直すことになるからです。そのため、カードの外側にもう一段包む要素を用意し、そちらをコンテナにする必要があります。既存のテーマやテンプレートに後から組み込む場合、この「もう一段の包み」をどこに置くかが最初の検討事項になります。

次に、container-typeにsizeを指定すると高さがつぶれることがある点です。sizeは縦横両方の大きさを条件にできる指定ですが、ブラウザは中身を見ずにコンテナの大きさを決めるため、高さや最小の高さ、縦横比を明示していないと高さが0pxになってしまいます。MDNも、コンテナの宣言には封じ込め(containment)が伴い、それは性能のために必要な仕組みだと説明しています。多くの場合は横方向だけを見るinline-sizeで十分で、縦方向が本当に必要な場面に限ってsizeを選ぶのが無難です。

最後に、条件の値にカスタムプロパティを使えない点です。デザインシステムで境目の幅を変数にまとめている場合でも、コンテナクエリの条件にvar()を書くことはできません。カスタムプロパティは要素の親子関係に沿って値が受け継がれるため、クエリの中でその値自体を書き換えると判定が循環してしまうからです。

スタイルクエリなど周辺の仕様も広がっている

今回のSmashing Magazineの記事が扱っているのは、大きさを条件にするサイズクエリです。MDNの解説を読むと、コンテナクエリの仕組みはそれだけではありません。現在は、サイズクエリ、コンテナの名前だけで絞り込む名前のみのクエリ、スタイルクエリ、スクロールの状態を条件にするクエリ、アンカー配置の状態を条件にするクエリ、の5種類が整理されています。

このうちスタイルクエリは、コンテナの計算済みのスタイルを条件にするものです。MDNによると、現時点で実際に条件にできるのはカスタムプロパティに限られ、通常のCSSプロパティを条件にする書き方はまだどのブラウザにも実装されていません。それでも、親要素に設定したテーマ用の変数の値によって子要素の見た目を切り替える、といった使い方はすでに検討できます。@propertyで型を登録しておくと、blueと#0000ffのように書き方の違う同じ色も一致として扱われる、という細かな挙動も解説されています。対応状況はブラウザごとに差があるので、採用する前に互換性の表を確認しておくのが安心です。

サイズクエリの基本がまだ手に馴染んでいない段階で、周辺の仕様まで一度に追う必要はありません。ただ、部品の置かれた状況をCSS側で判断する方向へ仕様全体が広がっていることは、頭の片隅に置いておく価値があります。

既存サイトへの取り入れ方

中小企業のサイトや地方の制作案件で、いきなり全体をコンテナクエリ前提で組み直す必要はないでしょう。記事の筆者も、すべてのプロジェクトでメディアクエリをコンテナクエリに置き換えるべきだとは考えていないと明言しています。

現実的なのは、置き場所によって崩れやすい部品から試すやり方です。お知らせの一覧カード、商品や事例の紹介カード、サイドバーにも本文にも置かれるバナーなど、同じ部品を複数の場所で使い回しているところが候補になります。こうした部品は、これまで置き場所ごとの追加指定で調整してきたことが多く、その追加指定を減らせるかどうかで効果を判断しやすいはずです。

書き方がメディアクエリに似ているぶん、使い分けの考え方さえ押さえてしまえば導入の壁はそれほど高くありません。ページの骨組みは画面の幅で、部品の中身は置かれた場所の幅で決める。この線引きを一度チーム内で共有しておくと、次のサイト改修のときに部品の作り方を見直すきっかけになりそうです。

[1994-2002]
ITベンチャーの幹部として、8年間で数名の企業を500名以上の企業に成長させることに貢献。95年より独学でwebデザインを学ぶ。

[2002-2023]
米国法人のwebデザイン会社のCEOを務め数々の賞を受賞。

[2023〜]
AI事業開始に伴い、つくば市を拠点として株式会社RESONIXを起業。