コンテナクエリが登場
非常にご要望の多かったデベロッパー向け機能の一つがウェブブラウザに搭載されました。Chromium 105 と Safari 16 では、これらのブラウザでサイズベースのコンテナクエリを作成し、コンテナ クエリ ユニット値を使用できるようになりました。サイズベースのコンテナクエリと cq
単位をさらに使いやすくするために、Chrome の Aurora チームでは、より多くのブラウザとユースケースに対応するよう Container Query Polyfill の更新に取り組んでおり、この強力な機能を今すぐ安心してお使いいただけるようになっています。
コンテナクエリとは
コンテナクエリは CSS の機能です。これを使用すると、親要素の対象物をターゲットにして子のスタイルを設定するロジックを作成できます。親のサイズをクエリすることで、真にコンポーネント ベースのレスポンシブ デザインを作成できます。これは、ビューポートのサイズ情報のみを提供するメディアクエリのようなものよりも、はるかに詳細で有用な情報です。
コンテナクエリを使用すると、ページの場所に応じて表示を変えられる再利用可能なコンポーネントを作成できます。これにより、ページやテンプレート全体で復元性と応答性が大幅に向上します。
コンテナクエリの使用
たとえば、次のような HTML があるとします。
<!-- card parent -->
<div class=”card-parent”>
<div class=”card>
<!-- card contents -->
…
</div>
</div>
コンテナクエリを使用するには、まずトラッキングする親要素に包含を設定する必要があります。これを行うには、container-type
プロパティを設定するか、container
短縮形を使用してコンテナタイプとコンテナ名を同時に設定します。
.card-parent {
/* query the inline-direction size of this parent */
container-type: inline-size;
}
これで、@container
ルールを使用して、最も近い親に基づいてスタイルを設定できるようになりました。上記の画像のように、カードが 1 列から 2 列になるようなデザインの場合、次のように記述します。
@container (min-width: 300px) {
.card {
/* styles to apply when the card container (.card-parent in this case) is >= 300px */
/* I.e. shift from 1-column to 2-column layout: */
grid-template-columns: 1fr 1fr;
}
}
より明確で明示的にするために、親要素のコンテナに名前を付けます。
.card-parent {
container-type: inline-size;
/* set name here, or write this in one line using the container shorthand */
container-name: card-container;
}
次に、前のコードを次のように書き換えます。
@container card-container (min-width: 300px) {
.card {
grid-template-columns: 1fr 1fr;
}
}
コンテナクエリ ユニット
コンテナクエリをさらに便利にするために、コンテナベースの単位値を使用することもできます。次の表に、コンテナの単位となる値と、それらがコンテナのサイズにどのように対応するかを示します。
単位 | 基準 |
---|---|
cqw | クエリコンテナの幅の 1% |
cqh | クエリコンテナの高さの 1% |
cqi | クエリコンテナのインライン サイズの 1% |
cqb | クエリコンテナのブロックサイズの 1% |
cqmin | cqi または cqb のうち小さい方 |
cqmax | cqi または cqb の大きい方 |
コンテナベースのユニットの使用方法の一例として、レスポンシブ タイポグラフィがあります。ビューポートを基準とした単位(vh
、vb
、vw
、vi
など)を使用して、画面上の任意の要素のサイズを調整できます。
.card h2 {
font-size: 15cqi;
}
このコードでは、フォントサイズがコンテナのインライン サイズの 15% になります。つまり、インライン サイズ(幅)が大きいほど大きくなり、小さいほど小さくなります。さらにこれをさらに進めるには、clamp()
関数を使用してタイポグラフィに最小サイズと最大サイズの上限を設定し、コンテナサイズに基づいてレスポンシブにサイズを調整します。
.card h2 {
font-size: clamp(1.5rem, 15cqi, 3rem);
}
これで、ヘッダーが 3rem
または .5rem
より小さくなることはありませんが、その間にコンテナのインライン サイズの 15% が使用されます。
このデモではさらに一歩進め、幅の広いカードが 2 列表示で表示されるため、サイズ範囲が小さくなります。
コンテナクエリのポリフィル
コンテナクエリはきわめて強力な機能であるため、ユーザーが安心してコンテナ クエリをプロジェクトに組み込むことができ、ブラウザ サポートがその大きな部分を占めていることを知っておきましょう。そのため、Google は Container Query Polyfill の改善に取り組んできました。このポリフィルは以下で一般的なサポートを備えています。
- Firefox 69 以降
- Chrome 79 以降
- Edge 79 以降
- Safari 13.4 以降
圧縮したときのサイズは 9 KB 未満で、ResizeObserver と MutationObserver を併用して、現在安定版のブラウザで利用可能な @container クエリ構文を完全にサポートします。
- 個別のクエリ(
width: 300px
とmin-width: 300px
)。 - 範囲クエリ(
200px < width < 400px
とwidth < 400px
)。 - プロパティとキーフレームでのコンテナの相対的な長さの単位(
cqw
、cqh
、cqi
、cqb
、cqmin
、cqmax
)。
コンテナクエリのポリフィルを使用する
ポリフィルを使用するには、次のスクリプトタグをドキュメントの先頭に追加します:
<script type="module">
if (!("container" in document.documentElement.style)) {
import("https://unpkg.com/container-query-polyfill@^0.2.0");
}
</script>
また、サービスを使用して User-Agent
に基づいて条件付きでポリフィルを配信することも、独自のオリジンで自己ホストすることもできます。
最適なユーザー エクスペリエンスを実現するには、最初はスクロールしないと見えない範囲のコンテンツにのみポリフィルを使用し、表示の準備が整うまで @supports
クエリを使用して一時的に読み込みインジケーターに置き換えることをおすすめします。
@supports not (container-type: inline-size) {
.container,
footer {
display: none;
}
.loader {
display: flex;
}
}
十分に高速なネットワークやデバイス、またはコンテナクエリをネイティブにサポートしているデバイスでは、この読み込みインジケーターは表示されません。
新しいポリフィル機能
更新されたポリフィルは、以下をサポートしています。
- ネストされた
@container
ルール。 @supports
クエリと@media
クエリの下に@container
ルールをネストできます(その逆も同様)。@supports (container-type: inline-size)
などの条件付き CSS は、ポリフィルの読み込み後に渡されます。- CSS 構文が完全にサポートされました(構文的に有効な場所にコメントを追加しても問題はなくなりました)。
- 垂直書き込みモード(書き込みモードによる)。
- コンテナの相対単位(
cqw
、cqh
など)は、クエリ条件、プロパティ宣言、アニメーション キーフレーム内でサポートされています。rem
とem
はクエリ条件でサポートされています。 - コンテナのクエリ構文が拡張されました。
- 範囲の構文(例:
(200px < width < 400px)
)。 - 等式クエリ(例:
(width = 200px)
)。
- 範囲の構文(例:
::before
や::after
などの疑似要素。:is(...)
または:where(...)
のないブラウザは、オプションの回避策としてサポートされますorientation
とaspect-ratio
の特徴クエリ。- 特徴に基づいてクエリを正しくフィルタリングする(たとえば、
container: inline-size
に対するheight
のクエリは、水平書き込みモードでは正しく禁止されます)。 - DOM ミューテーション(たとえば、実行時に
<style>
要素と<link>
要素が削除される)。
ポリフィルの制限事項と警告
コンテナクエリのポリフィルを使用している場合、注意すべきいくつかの機能が不足しています。
- Shadow DOM はまだサポートされていません。
- コンテナの相対単位(
cqw
やcqh
など)は、@media
クエリ条件ではサポートされていません。- Safari: コンテナの相対単位は、15.4 より前のアニメーション キーフレームでサポートされていません。
calc()
、min()
、max()
などの数学関数は、クエリ条件ではまだサポートされていません。- このポリフィルは、インラインの同一オリジンの CSS でのみ機能します。クロスオリジン スタイルシート、および iframe 内のスタイルシート(ポリフィルが手動で読み込まれる場合を除く)はサポートされていません。
layout
とstyle
の包含には、基盤となるブラウザのサポートが必要です。- Safari 15.4 以降
- 現時点では、Firefox はスタイルの包含をサポートしていませんが、現在対応は行っています。
警告
- FID と CLS への影響を防ぐために、ポリフィルでは、同期的に読み込まれても、最初のレイアウトがいつ行われるかは保証されません。ただし、LCP の不当な遅延を回避しようとする場合を除きます。つまり、First Paint では使用しないでください。
ResizeObserver Loop Errors
を生成します。元のポリフィルでも同じことができますが、注意しておきましょう。これは、container-type: inline-size
のブロックサイズがクエリの評価後に変化する可能性が高いものの、ResizeObserver
はブロックサイズの変更を考慮しないと判断できないために発生します。- このポリフィルは、ウェブ プラットフォーム テストに対してテストされ、70% に合格しました。これは、JavaScript API などの特定の機能がポリフィルされておらず、合格率が意図的に 70% に近づいているためです。
- 以下より古いブラウザを使用している 2.23% のユーザーには、
:where()
の回避策が必要です。- Safari 14
- クロム 88
- Edge 88
- Samsung インターネット 15
- Firefox 78