【CSS】コンテナクエリについて / メディアクエリとの違い〜文法までを紹介
NNCの中里です。ご無沙汰しております。スタッフばかりに記事を書かせてしまい、自分自身で記事を書くのは実に2年ぶりになります。
この2年間キャンプへ行ったりキャンプへ行ったりと色々とありました・・・がその辺りは割愛して、今回はコンテナクエリについてお話をしたいと思います。
https://caniuse.com/css-container-queries
コンテナクエリが主要ブラウザに対応してから2ヶ月ほど経った(2023年4月現在)ので、「弊社でもそろそろ導入しますか」と緩い感じで調べ始めました。
まず最初に感じたのは「メディアクエリとの違い」や「使い分け方」が分かりづらかったので、その辺りから説明したいと思います。
説明はいいから文法が知りたい!という方はこちらからご覧ください
目次
メディアクエリとコンテナクエリ
まず「コンテナクエリって何?メディアクエリと何が違うの?」という方に説明すると「メディアのサイズ(ビューポート)を基準として命令を出すものがメディアクエリ」であるのに対し、「コンテナ(祖先要素)のサイズを基準として命令を出すものがコンテナクエリ」になります。
下のイメージを見ていただくとより分かりやすいですね。
これまでレスポンシブWebデザインにおいては「メディアのサイズ」を基準としてレイアウトやデザインの命令を出していましたね。
上のイメージのように、メディアクエリの記述を使い「メディアのサイズが〇〇px以下になったらメニューをハンバーガーに切り替える / Section Aと Section Bを上下に並べる」といった命令でタブレットやスマホに対してレイアウトの指定をしてきました。
メディアクエリの問題点
しかしレスポンシブWebデザインで常に可変し続けるようなサイトを作る場合、PCからタブレット・スマホの間でレイアウトが崩れやすく(見辛く)なるタイミングもあります。
上のようにメディアのサイズが中途半端に小さくなった際、Section A部分が明らかに見づらくなってしまう経験がどなたにもあると思います。(ぼくは結構あります)
Section Aの幅がここまで小さくなった場合、サムネイルとテキストは上下に並んだ方が見やすいはずです。
このような時にもこれまではメディアクエリを使い対応してきましたが、この時の基準は「メディアのサイズ」ではなく「Section Aのコンテナサイズ」を基準とした方が考えやすくなります。
「Section Aのコンテナサイズが〇〇px以下になったらサムネイルとテキストを上下に並べる」という命令が出せるのがコンテナクエリになります。
ここで感じるのが「え?それメディクエリでも同じことできるじゃん」と言うことです。
当然、僕もそのように感じました。
「メディアのサイズが〇〇px以下になったらサムネイルとテキストを上下に並べる」と指示すれば良いわけですよね。
コンテナクエリの利点
メディアのサイズと言う大きな範囲を基準とするより、コンテナのサイズという細かな範囲を基準にすることができるというのがコンテナクエリの利点かなと感じています。
例えばサムネイルサイズが100pxだとして、メディアのサイズがいくつになったらテキストが見づらくなるかと考えようとすると、基準が大きすぎて想像しづらいと思います。(検証ツールで測れば良いだけの話ですが)
「サムネイルサイズが100pxだからコンテナのサイズ(SectionAの横幅)が150px以下くらいになったら、テキストの幅が小さくて読みづらくなりそうだなぁ」というのは容易に想像できますよね。
このように細かく可変をさせる際にはとても便利そうです。
メディアクエリとの使い分け
結論として完全にコンテナクエリに移行していくのではなく、
- メディアを基準に大きな構造を可変させていく箇所はメディアクエリ
(メニューの切り替えや、大きなレイアウトの変更など) - コンテナを基準に細かく可変をさせていく箇所はコンテナクエリ
(可変時におけるセクション内の調整など)
と使い分けると良いのかなと感じました。
もちろん今後色々な使われ方がしていく中で、それぞれの役割なども変わっていくこともあると思います。
実際の制作の中で「あぁ、こういう時に使うと便利だなぁ」と感じることもありそうだなと思うので、積極的に使っていきたいですね!
コンテナクエリの記述方・文法
コンテナクエリはcontainer-typeプロパティと@containerルールを使用します。
containerプロパティを指定したセレクタがコンテナクエリの基準となり、@containerルールを使って「基準となるコンテナのサイズによって指示を切り替える」イメージです。
container-typeプロパティ
基準としたいセレクタに対してcontainer-typeプロパティを記述します。
div {
container-type: inline-size;
}
container-typeの値は以下の通りです。
- normal : 通常動作
- inline-size インライン方向(横方向)のサイズに応じる
- size インライン方向(横方向)とブロック方向(縦方向)のサイズに応じる
幅を基準とする場合はinline-sizeを適用します。
container-nameプロパティ
コンテナに名前をつけたい場合、container-nameプロパティを使用します。
複数の祖先要素にcontainer-typeを記述した際に、どちらを基準とするか明記する必要がある場合にはcontainer-nameプロパティで名前をつけておきます。(値 / 名前は任意でつけることができます)
必須の記述ではないため、記述がない場合は最も近い祖先要素が基準となります。
div {
container-type: inline-size;
container-name: layout;
}
値(名前 / 上の記述例の layout 部分)は任意でつけることができます。
containerプロパティ
container-typeプロパティとcontainer-nameプロパティのショートハンドです。
まとめて記述したい場合に用います。
値はname/typeの順で記述します。
div {
container: layout/inline-size;
}
@containerルール
@containerの記述でコンテナサイズを条件としてCSSを記述します。
@container (min-width:300px) {
.main {
background-color: #ffc;
}
}
上の記述だと基準となるコンテナの幅が300pxを超えた場合、子要素の.mainの背景色が#ffcとなります。
container-nameプロパティで基準となるコンテナに名前をつけている場合、以下のように名前を指定して記述することができます。
@container layout (min-width:300px) {
.main {
background-color: #ffc;
}
}
HTML,CSSの記述例
最後にHTMLとCSSの記述例を紹介します。
See the Pen container query by hiroshi nakazato (@nnc_nakazato) on CodePen.
コードとResultの画面が2分割になっている状態で見ると、リストの文字色が黒になっていると思います。
左側のコード画面を閉じ、Resultの画面が広がるとリストの文字色が赤く変化すると思います。
@containerルールでmin-width:500pxとしているため、コンテナのサイズが500pxを超えたら文字色が変わる仕様になっています。
まとめ
コンテナを基準として指示が出せるようになったことで、レスポンシブWebデザインにおいて細やかな設定がしやすくなりましたね。
初めて学ぶ方にとってはメディアクエリとの違いが分かりづらい部分になりますが、この記事を見ながらコードを書いていくと違いやメリットが見えてくると思います。
また次に記事を書くのが2年後にならないよう、年内にあと1つくらいは書きたいと思います!(スタッフは定期的に記事を書いてくれています)
参考にさせていただいたサイト、記事になります: