原文:https://ishadeed.com/article/container-query-units/
作者:Ahmad Shadeed
译者:Levix
数日前、Miriam Suzanne が CSS コンテナクエリ単位のサポートについてのツイートを投稿しているのを見ました。これは最初に Github のUna Kravetsによって提案されました。私はそれを試してみたくなり、CSS コンテナクエリからどのようにさらなる可能性を引き出せるかを見てみました。
各単位がどのように機能するか、またどのようにしてコンポーネントが親の幅に適応するために 1 つ(または複数)の単位を使用できるかを説明しようと思います。もし CSS コンテナクエリについてまだ聞いたことがない場合、私は多くの例を紹介した記事と、コンテナクエリがデザイナーの仕事にどのように影響するかについての記事を書いていますので、この記事を読む前にそれらを読むことをお勧めします。
温かいヒント:CSS コンテナクエリは、実験的なフラグを持つ Chrome Canary バージョンのブラウザでのみサポートされています。他のバージョンで使用するには、chrome://flags で「Enable CSS Container Queries」を検索してこの機能を有効にしてください。
では、詳しく見ていきましょう。
はじめに#
CSS には、さまざまなシーンで使用できる多くの単位があり、最も一般的なのはpx
、rem
、およびem
です。CSS コンテナクエリの動作に似た単位があるとすれば、それはビューポート単位だと思います。
CSS ビューポート単位は、ブラウザのビューポートサイズ(幅または高さ)に基づいて機能します。これは素晴らしいことですが、ビューポートサイズに関連する単位を常に使用したいわけではありません。コンテナの幅に対してクエリを行いたい場合はどうでしょうか?これがクエリ単位の役割です。
問題をより明確にするために、ビューポート単位とクエリ単位の違いを強調したいと思います。以下の図を見てください:
左側の領域では、font-size
がビューポート幅に対してrem
とvw
によって制御されています。特定の状況ではこの方法が機能しますが、ビューポートサイズに基づいているため、予期しない問題を引き起こす可能性があります。
font-size
、padding
、margin
などの問題を扱う際に、クエリ単位は私たちの時間と労力を節約できます。クエリ単位を使用して、手動でフォントサイズを増やす代わりに使用できます。
以下の例を参照してください。
私たちは、スタックされたカード型コンポーネントの開始状態を持っており、コンテナが大きくなるにつれて、徐々にメインバナーのスタイルに変わります。このようなコンポーネントでは、以下の内容を変更する必要があるかもしれません:
- サムネイルサイズ
- フォントサイズ
- 要素間の間隔
CSS クエリ単位がなければ、上記の内容を手動で変更する必要があります。
.card {
/* スタックされた基本スタイル */
}
.card__title {
font-size: 1rem;
}
/* 横スタイル、v1 */
@container (min-width: 400px) {
.card__title {
font-size: 1.15rem;
}
}
/* 横スタイル、v2 */
@container (min-width: 600px) {
.card__title {
font-size: 1.25rem;
}
}
/* ヒーロースタイル */
@container (min-width: 800px) {
.card__title {
font-size: 2rem;
}
}
.card__title
のフォントサイズが異なるコンテナクエリに応じてどのように変化するかに注目してください。クエリ単位と CSS のclamp()
関数を使用することで、これを強化し、font-size
を繰り返し設定するのを避けることができます。
.card__title {
font-size: clamp(1rem, 3qw, 2rem);
}
これにより、font-size
を一度だけ定義すればよく、直感的に比較したい場合は以下のようになります:
CSS ビューポート単位に慣れているなら、これはあなたにとって馴染み深いでしょう。これは、ブラウザのビューポートではなくコンテナに基づいてクエリを行うようなものです。シンプルですよね?
クエリ単位#
クエリ単位が解決すべき問題を理解したところで、CSS 仕様に基づいてこれらの単位をさらに理解しましょう:
- クエリ幅(qw):コンテナ幅の 1%。例えば、5qw はコンテナ幅の 5% として解釈されます。
- クエリ高さ(qh):コンテナ高さの 1%。例えば、5qh はコンテナ高さの 5% として解釈されます。
- クエリ最小値(qmin):クエリ幅
qw
またはクエリ高さqh
の小さい方。 - クエリ最大値(qmax):
qw
またはqh
の大きい方。
さらに、qi
とqb
という 2 つの単位もあります。これらはそれぞれクエリインラインとクエリブロック(サイズ)を表し、異なる書き方のモードがある場合に適用されます。
ケーススタディと例#
カードコンポーネント#
以前に説明したカードの例に加えて、スタックされたカードでクエリ単位を使用することもできます。コンテナの幅に基づいてフォントサイズを少し大きくしたいと考えています。
フォントサイズがコンテナサイズに応じてわずかに大きくなることに注意してください。これは、どこに置いても機能するスタックカードを作成するのに非常に役立ちます。
重み付けに基づくfont-size
の変更#
ある要素が別の要素よりも大きい場合、それはより重要であることを示しています。良い例はサイドバーとメインコンテンツで、<aside>
内のタイトルサイズは<main>
部分のタイトルよりも小さくするべきです。
<aside>
内のタイトルが<main>
内のタイトルよりも小さいことに注意してください。クエリ単位のおかげで、これを簡単に実現できます。
まず、<aside>
と<main>
をインラインサイズコンテナとして定義する必要があります。
aside,
main {
container: inline-size;
}
次に、セクションタイトルにクエリ単位を設定し、下部のマージンにもクエリ単位を使用できます。
.section-title {
font-size: clamp(1.25rem, 3qw, 2rem);
margin-bottom: clamp(0.5rem, 1.5qw, 1rem);
}
プロフィールコンポーネント#
プロフィールは、小さなコンテナ(例えば、サイドバー)に配置することも、モバイルビューポートに表示することも、大きなコンテナ(ページタイトルなど)に表示することもできます。
私たちは、そのコンテナの幅に適応するコンポーネントを構築できます。この例では、ユーザーのアバターとフォントサイズがそのコンテナの幅に応じて変わります。
.bio {
container: inline-size;
}
.c-avatar {
--size: calc(60px + 10qw);
width: var(--size, 100px);
height: var(--size, 100px);
margin-bottom: clamp(0.5rem, 3qmin, 2rem);
}
カウンター付きタイトル#
特定の状況では、記事の本文のタイトルの横にカウンターを表示する必要があります。これはクエリ単位の完璧な使用例です。
.article-body {
counter-reset: heading;
}
h2 {
container: inline-size;
font-size: clamp(1.25rem, 3qw, 2rem);
margin-bottom: clamp(0.5rem, 1.5qw, 1rem);
}
h2:before {
--size: calc(1.25rem + 3qw);
content: counter(heading);
counter-increment: heading;
width: var(--size);
height: var(--size);
font-size: calc(0.85rem + 1qw);
margin-right: calc(var(--size) / 4);
}
動的間隔#
私たちは、ビューポート単位を使用して動的間隔の CSS グリッドを作成しました。それは以下のようになります:
.wrapper {
gap: calc(1rem + 2vw);
}
これは素晴らしいですが、特定のラッパー内のコンポーネントはどうでしょうか?ビューポート単位を使用するのはうまくいかないため、この場合、クエリ単位を使用するのは良い解決策です。
.card {
display: flex;
flex-direction: column;
gap: calc(0.5rem + 1qmin);
}
コンポーネントが横スタイルに切り替わると、間隔が大きくなります。
定義されたコンテナなしでクエリ単位を使用した場合に何が起こるか?#
仕様によると:
適切なクエリコンテナがない場合、その軸の小さいビューポートサイズを使用します。
ブラウザは、ビューポート単位を処理するのと同様にクエリ単位を処理します。以下の例を見てください:
h2 {
font-size: clamp(1.25rem, 3qw, 2rem);
}
<h2>
にコンテナが定義されていない場合、ブラウザは3qw
をビューポート幅の3%
として解釈します。これは、定義されたコンテナがない場合にクエリ単位を使用すると予期しない結果を引き起こすことを意味します。
この記事を楽しんでいただけたら幸いです。お読みいただきありがとうございました!