CSS コンテナクエリの準備はできてる? 安定版のブラウザにサポート、ポリフィルも大幅にアップデートされました

コンテナクエリは今までのメディアクエリのスクリーンベースではなく、親コンテナをベースにして子要素のスタイルを定義できます。レイアウトやコンポーネントをはじめ、レスポンシブ対応のフォントサイズにも大活躍する新機能です。

そんなコンテナクエリが安定版のブラウザにサポートされ、ポリフィルも大幅にアップデートされたので、基礎知識、基本的な使い方、便利な新単位、ポリフィルの使い方と注意事項を紹介します。

CSSの新機能でネックになるのが、ブラウザのサポート。しかし、CSSの新機能コンテナクエリは、違います。サポートされていないブラウザ用にポリフィルも同時に開発されており、2年くらい前のブラウザでもサポートされています。

CSSのコンテナクエリが主要ブラウザにサポート、ポリフィルも大幅にアップデート

Container queries begin to land in stable browsers while the polyfill gets a big update
by Una Kravets, Gerald Monaco

下記は各ポイントを意訳したものです。
※元サイト様のライセンスに基づいて翻訳しています。

コンテナクエリが登場!

これはエキサイティングなニュースです!
デベロッパーからの要望がもっとも高かった機能「コンテナクエリ」が、ブラウザに実装されました!

2022年10月現在、Chrome 105+(Edgeも105+)とSafari 16でサイズベースのコンテナクエリが使用でき、コンテナクエリの単位も使用できます。

また、ChromeのAuroraチームはコンテナクエリのポリフィルのアップデートに尽力しており、より多くのブラウザとユースケースをサポートできるようなりました。
参考: CSSの新機能コンテナクエリのポリフィルがこれほど使いやすく、Googleから提供されたことは素晴らしい

コンテナクエリはCSS Containment Module Level 3の一部です。この仕様には新しい単位値とサイズとスタイルの両方のコンテナタイプがカバーされていますが、ブラウザではサイズのみのサポートから開始されています。そのため、この記事ではサイズのコンテナにフォーカスをあてています。

コンテナクエリとは

コンテナクエリとは、親要素をターゲットにして子要素のスタイルを定義できるCSSの新機能です。

たとえば、親要素のサイズに応じて、コンポーネントベースのレスポンシブデザインを実装できます。今まではビューポートのサイズ情報のみを参照するメディアクエリでしたが、コンテナクエリははるかに詳細で有用です。

メディアクエリとコンテナクエリ

左: メディアクエリ、右: コンテナクエリ

コンテナクエリを使用すると、再利用可能なコンポーネントを作成でき、ページ内の配置場所に応じて異なるスタイルで表示できます。これにより、ページやテンプレートの種類によらず、レスポンシブ性の高いコンポーネントを作成できます。

【訳者注】
コンテンツ用とサイドバー用のカード、コンテンツ用とサイドバー用の検索ボックスなど、配置場所に応じて異なるスタイルで表示できます。

コンテナクエリの使い方

たとえば、下記のようなHTMLがあるとします。

コンテナクエリを使用するには、最初にターゲットにする親要素にコンテナを設定します。container-typeプロパティを記述するか、containerプロパティというショートハンドを記述します。

次に、@containerルールを使用して、もっとも近い親に基づいてスタイルを設定できます。上記の画像のように、カードを1カラムから2カラムになるデザインの場合、下記のように定義します。

親要素のコンテナに名前をつけて、より明示的にします。

containerプロパティのショートハンドで定義すると、下記のようになります。

そして、先ほどのCSSを下記のように書き直します。

これで親要素のサイズに応じて、1カラムと2カラムのカードが実装できます。
真ん中のカードのサイズが変わることに注目してください。

実際の動作は、デモページでご覧ください。

See the Pen
Simplified CQ Card Demo in Grid - Polyfill
by web.dev (@web-dot-dev)
on CodePen.

コンテナクエリの新しい単位

コンテナクエリをさらに便利にするために、コンテナベースの単位も使用できます。下記はコンテナ単位とそれらがどのようにコンテナのサイズに対応しているかです。

  • cqw: クエリ コンテナの幅の 1%
  • cqh: クエリ コンテナの高さの 1%
  • cqi: クエリ コンテナのインラインサイズの 1%
  • cqb: クエリ コンテナのブロックサイズの 1%
  • cqmin: cqiまたはcqbの小さい方の値
  • cqmax: cqiまたはcqbの大きい方の値

コンテナベースの単位をどのように使用するかの一例が、レスポンシブ対応のフォントサイズです。

上記のCSSでは、font-sizeをコンテナのインラインサイズの15%に定義しています。つまり、インラインサイズ(幅)が大きくなるとフォントサイズも大きくなり、小さくなるとフォントサイズも小さくなります。

さらに、clamp()関数を使用すると、最小サイズと最大サイズを設定でき、コンテナのサイズに応じてレスポンシブにフォントサイズを変更できます。

参考: CSSの比較関数が便利すぎる!min(), max(), clamp()の使い方を詳しく解説

このCSSで、ヘッダのフォントサイズが3remより大きくなったり、0.5remより小さくなったりすることはありません。そして、その間のフォントサイズはコンテナのインラインサイズの15%が適用されます。

実際の動作は、デモページでご覧ください。

See the Pen
CQ Card with Responsive Type - Polyfill
by web.dev (@web-dot-dev)
on CodePen.

このデモではさらに一歩進んで、2カラムで表示されるように幅の広いカードをより小さいサイズ範囲にしています。

コンテナクエリのポリフィル

コンテナクエリは非常にパワフルで魅力的な機能であるため、プロジェクトで安心して使用するには、ブラウザのサポートが大きな役割を占めていることを理解しています。そのため、わたし達はコンテナクエリのポリフィルにも取り組んできました。ポリフィルは、以下のブラウザをサポートしています。

  • Firefox 69+
  • Chrome 79+
  • Edge 79+
  • Safari 13.4+

参考: CSSの新機能コンテナクエリのポリフィルがこれほど使いやすく、Googleから提供されたことは素晴らしい

圧縮時のサイズは9Kb以下、MutationObserverでResizeObserverを使用して、現在安定版のブラウザで利用できる@containerのクエリ構文を完全にサポートしています。

  • 個別クエリ (width: 300px, min-width: 300pxなど)
  • 範囲クエリ(200px < width < 400px, width < 400pxなど)
  • コンテナベースの単位(cqw, cqh, cqi, cqb, cqmin, cqmax

コンテナクエリのポリフィルの使い方

コンテナクエリのポリフィルを使用するのは、簡単です。
下記のscriptタグをhead内に記述するだけです。

また、User-Agentに基づいて条件付きでポリフィルを配信するサービスを利用したり、独自にポリフィルをセルフホスティングすることも可能です。

すべてのブラウザでコンテナクエリのサポートがリリースされているか、ロードマップに記載されているので、ポリフィルを他のコードにバンドルすることは避けることをお勧めします。

最高のユーザーエクスペリエンスを得るために、最初はスクロールせずに見えるコンテンツでポリフィルを使用し、@supportsクエリでポリフィルがロードされる準備が整うまで一時的にローディングのインジケーターに置き換えることをお勧めします。

高速なネットワークとデバイス、またはコンテナクエリをネイティブにサポートするデバイスでは、このローディングのインジケータが表示されることはありません。

このテクニックは、ロード時のジャンクを減らすためにLCPを効果的にトレードオフするので、特にローエンドのデバイスでは結果的に前者のリグレッションが発生する可能性があります。

新しいポリフィルの機能

2022/9にアップデートされたポリフィルは、以下をサポートします。

  • ネストされた@containerルール。
  • @supports@mediaクエリの下での@containerルールのネスト、およびその逆に入れ子もサポートされています。
  • @supports (container-type: inline-size)のような条件付きCSSはポリフィルがロードされた後に渡されます。
  • CSSの構文を完全サポート(構文上有効なコメントをどこに書いても問題はありません)。
  • 縦書きモードをサポート(writing-mode経由)。
  • コンテナ相対単位(cqw, cqhなど)はクエリ条件、プロパティ宣言、アニメーションキーフレームでサポートされています。拡張コンテナクエリ構文は、
    • 範囲指定構文((200px < width < 400px)など)
    • 等式クエリ(width = 200pxなど)
  • ::before, ::afterなどの疑似要素をサポート。
  • :is(...), :where(...)がないブラウザは、オプションの回避策でサポートされます。
  • orientation, aspect-ratioもサポートされています。
  • 機能に基づくクエリの正しいフィルタリング (たとえば、container: inline-sizeheightクエリは、横書きモードでは正しく許可されません)。
  • DOMの変更(たとえば、<style><link>要素が実行時に削除される)。

アップデートされたポリフィルでは、size()でサイズクエリを囲む必要があるレガシーなサイズクエリ構文(たとえば、size(width >= 200px))をサポートしなくなりました。

ポリフィルの制限と注意事項

コンテナクエリのポリフィルを使用する場合、注意すべき点がいくつかあります。

ポリフィルの制限

  • Shadow DOMはまだサポートされていません。
  • コンテナ相対単位(cqw, cqhなど)は、@mediaクエリ条件ではまだサポートされていません。
    • Safari: コンテナ相対単位は、15.4より前のアニメーションキーフレームではサポートされていません。
  • calc(), min(), max() またはその他の数学関数は、クエリ条件ではまだサポートされていません。
  • このポリフィルは、インラインおよび同一オリジンのCSSに対してのみ機能します。クロスオリジンのCSSやiframe内のCSSは (ポリフィルが手動で読み込まれていない限り) サポートされません。
  • layoutstyleの保持には、基本的なブラウザのサポートが必要です。
    • Safari 15.4+
    • Firefoxは現時点ではスタイル コンテインメントをサポートしていませんが、現在取り組んでいます。

ポリフィルの注意事項

  • FIDとCLSへの影響を防ぐために、ポリフィルはたとえ同期的にロードされたとしても、最初のレイアウトがいつ発生するかについては、LCPを不当に遅らせることを避けようとする以外、何の保証もしません。言い換えれば、最初のペイントについては依存しないでください。
  • ResizeObserver Loop Errorsを生成します。オリジナルのポリフィルでもこのようなことはありましたが、注意が必要です。これはcontainer-type: inline-sizeblock-sizeがクエリの評価後に変更される可能性が高いために発生しますが、ResizeObserverにはblock-sizeの変更を気にしないことを伝える方法がありません。
  • このポリフィルは、Web Platform Testsでテストを行い、70%の合格率を達成しました。これはJavaScript APIなどの一部の機能がポリフィルされていないためで、合格率は意図的に70%に近づけています。
  • 2.23%のより古いブラウザには、:where()の回避策が必要です。
    • Safari 14
    • Chromium 88
      • Edge 88
      • Samsung Internet 15
    • Firefox 78

sponsors

top of page

©2022 coliss