CSS と UI の新機能: I/O 2023 Edition

ここ数か月は、ウェブ UI の黄金時代を迎えています。新しいプラットフォーム機能がブラウザ間での緊密な導入に伴って導入され、これまで以上に多くのウェブ機能やカスタマイズ機能をサポートするようになりました。

ここでは、最近リリースされた、または近日リリース予定の、特にエキサイティングでインパクトのある 20 の機能を紹介します。

レスポンシブ

まずは新しいレスポンシブ デザイン機能から始めましょう。新しいプラットフォーム機能により、レスポンシブ スタイル情報を所有するコンポーネントとの論理インターフェースを構築できます。また、システム機能を活用してよりネイティブ感のある UI を提供するインターフェースを構築できます。また、ユーザー設定のクエリを使用して完全なカスタマイズが可能になるので、ユーザーがデザイン プロセスに関与できるようになります。

コンテナクエリ

対応ブラウザ

  • 105
  • 105
  • 110
  • 16

ソース

コンテナクエリは最近、すべての最新ブラウザで安定版になりました。これにより、親要素のサイズとスタイルをクエリして、子に適用するスタイルを決定できます。メディアクエリは、ビューポートの情報にのみアクセスして利用できます。つまり、ページ レイアウトのマクロ表示でのみ機能します。一方、コンテナクエリは、レイアウト内の任意の数のレイアウトをサポートできるより正確なツールです。

次の受信トレイの例では、[メインの受信トレイ] サイドバーと [お気に入り] サイドバーはどちらもコンテナです。それらのメールでは、グリッド レイアウトが調整され、利用可能なスペースに応じてメールのタイムスタンプの表示と非表示が切り替わります。これはページ内のまったく同じコンポーネントで、異なるビューに表示されるだけです

コンテナクエリがあるため、これらのコンポーネントのスタイルは動的です。ページサイズとレイアウトを調整すると、コンポーネントは個別に割り当てられたスペースに対応します。サイドバーが上部バーになり、スペースが増え、レイアウトがメインの受信トレイのように見えます。スペースが狭い場合は、両方とも縮小形式で表示されます。

コンテナクエリと論理コンポーネントの構築について詳しくは、こちらの投稿をご覧ください。

クエリのスタイル設定

対応ブラウザ

  • 111
  • 111
  • x
  • x

ソース

コンテナのクエリ仕様では、親コンテナのスタイル値をクエリすることもできます。この機能は現在、Chrome 111 で部分的に実装されており、CSS カスタム プロパティを使用してコンテナのスタイルを適用できます。

次の例では、カスタム プロパティ値(雨、晴れ、曇りなど)に格納されている気象特性を使用して、カードの背景とインジケーター アイコンのスタイルを設定しています。

@container style(--sunny: true) {
 .weather-card {
   background: linear-gradient(-30deg, yellow, orange);
 }

 .weather-card:after {
   content: url(<data-uri-for-demo-brevity>);
   background: gold;
 }
}

天気情報カードのデモ

これは、スタイルクエリの始まりにすぎません。将来的には、カスタム プロパティ値が存在するかどうかを判断し、コードの繰り返しを減らすブールクエリが実装される予定です。現在は、値の範囲に基づいてスタイルを適用する範囲クエリが検討されています。これにより、雨や雲に覆われている確率をパーセントで指定して、ここに示すスタイルを適用できます。

詳細とその他のデモについては、スタイルクエリに関するブログ投稿をご覧ください。

:has()

対応ブラウザ

  • 105
  • 105
  • 121
  • 15.4

ソース

強力で動的な機能に関して言えば、:has() セレクタは、最新のブラウザに実装される最も強力な新しい CSS 機能の 1 つです。:has() を使用すると、親要素に特定の子が存在するかどうか、またはそれらの子が特定の状態にあるかどうかを確認することで、スタイルを適用できます。つまり、実質的に親セレクタが用意されました。

コンテナクエリの例を基にして、:has() を使用してコンポーネントをさらに動的にします。「スター」要素を含むアイテムの背景はグレーで、チェックボックスがオンになっているアイテムの背景は青色になります。

デモのスクリーンショット

ただし、この API は親の選択に限定されません。親内の子のスタイルを設定することもできます。たとえば、アイテムにスター要素がある場合、タイトルは太字になります。これは .item:has(.star) .title で実現できます。:has() セレクタを使用すると、親要素、子要素、さらに兄弟要素にもアクセスできるため、毎日新しいユースケースが登場する非常に柔軟な API になります。

詳細とその他のデモについては、:has() に関するこちらのブログ投稿をご覧ください。

n 番目の構文

対応ブラウザ

  • 111
  • 111
  • 113
  • 9

ウェブ プラットフォームで、より高度な n 番目の子を選択できるようになりました。高度な n 番目の子構文では、新しいキーワード(「of」)が与えられます。これにより、An+B の既存のマイクロ構文を使用して、より限定されたサブセットを検索することができます。

特殊なクラスで通常の n 番目の子(:nth-child(2) など)を使用すると、ブラウザは、特別なクラスが適用された要素を選択し、これが 2 番目の子でもあります。これは、最初にすべての .special 要素を事前にフィルタしてから、そのリストから 2 番目の要素を選択する :nth-child(2 of .special) とは対照的です。

この機能について詳しくは、n 番目の構文に関する記事をご覧ください。

text-wrap: balance

スタイル内にロジックを埋め込むことができる場所は、セレクタとスタイルクエリだけではありません。タイポグラフィもその一つです。Chrome 114 以降では、text-wrap プロパティと値 balance を使用して、見出しにテキストの折り返しの分散を使用できます。

デモを試す

テキストのバランスを取るために、ブラウザは実質的に最小幅でバイナリ検索を実行し、追加の行が発生しません。1 つの CSS ピクセル(表示ピクセルではない)で停止します。バイナリ検索のステップをさらに最小限にするため、ブラウザは平均線幅の 80% から開始します。

デモを試す

詳しくは、こちらの記事をご覧ください。

initial-letter

対応ブラウザ

  • 110
  • 110
  • x
  • 9

ソース

ウェブ タイポグラフィのもう一つの優れた改善点は initial-letter です。この CSS プロパティを使用すると、インセット ドロップ キャップのスタイル設定をより適切に制御できます。

:first-letter 疑似要素で initial-letter を使用して、次の項目を指定します。文字を占める行数に基づく文字のサイズ。文字のブロック オフセット(「シンク」)。文字が配置されます。

intial-letter の使用方法について詳しくは、こちらをご覧ください。

動的ビューポート ユニット

対応ブラウザ

  • 108
  • 108
  • 101
  • 15.4

今日のウェブ デベロッパーが直面する一般的な問題の一つは、特にモバイル デバイスでフルビューポートのサイズが正確かつ一貫していることです。デベロッパーとしては、100vh(ビューポートの高さの 100%)を「ビューポートと同じ高さ」にしたいと考えるかもしれませんが、vh ユニットはモバイルでのナビゲーション バーの格納などを考慮していないため、長くなりすぎてスクロールが発生することもあります。

表示されるスクロールバーが多すぎる

この問題を解決するために、ウェブ プラットフォームに次のような新しい単位値が導入されました。 - 小さいビューポートの高さと幅(または svhsvw)。これはアクティブな最小のビューポートのサイズを表します。- 大きいビューポートの高さと幅(lvhlvw)。最大サイズを表します。- 動的なビューポートの高さと幅(dvhdvw)。

動的ビューポートのユニットは、追加の動的ブラウザ ツールバー(上部のアドレスや下部のタブバーなど)が表示されている場合と非表示の場合に、値が変化します。

新しいビューポート ユニットの可視化

これらの新しいユニットについて詳しくは、ビューポートの大、小、動的なユニットをご覧ください。

広色域の色空間

対応ブラウザ

  • 111
  • 111
  • 113
  • 15.4

ソース

ウェブ プラットフォームに新たに追加されたもう一つの重要な機能は、広色域の色空間です。ウェブ プラットフォームで広色域が利用可能になる前は、現代のデバイスでも見やすい鮮明な色で写真を撮ることはできましたが、その鮮明な値に合ったボタン、テキストの色、背景を得ることはできませんでした。

一連の画像が色域の広さと細さの間で移行され、色の鮮やかさとその効果が示されています。
使ってみる

現在は、REC2020、P3、XYZ、LAB、OKLAB、LCH、OKLCH など、さまざまな新しい色空間がウェブ プラットフォームで利用できるようになりました。HD カラーガイドで、ウェブの新しい色空間などについて紹介しています。

それぞれの新しい色空間の関係とサイズがわかるよう、さまざまな色で積み重ねられた 5 つの三角形。

DevTools では、色範囲がどのように拡大し、sRGB 範囲の終了点と広色域色範囲の開始点が白い線で示されているかをすぐに確認できます。

カラー選択ツールに色域ラインが表示されている DevTools。

カラーのツールが増えましたグラデーションの改良点も見逃せません。Adam Argyle は、ウェブ用の新しいカラー選択ツールとグラデーション ビルダーを試すための新しいツールも提供しています。このツールは gradient.style からお試しいただけます。

color-mix()

対応ブラウザ

  • 111
  • 111
  • 113
  • 16.2

ソース

展開後の色空間で展開するには、color-mix() 関数を使用します。この関数は、2 つの色値を混ぜて、色の混ざるチャネルに基づいて新しい値を作成します。混ぜる色空間は結果に影響します。oklch など、より視覚に訴える色空間で処理すると、sRGB などとは異なる色範囲になります。

color-mix(in srgb, blue, white);
color-mix(in srgb-linear, blue, white);
color-mix(in lch, blue, white);
color-mix(in oklch, blue, white);
color-mix(in lab, blue, white);
color-mix(in oklab, blue, white);
color-mix(in xyz, blue, white);
7 つの色空間(sRGB、linear-sRGB、lch、oklch、lab、oklab、xyz)のそれぞれについて異なる結果を示している。多くはピンクや紫色で、実際にはまだ青いものもあります。
デモを試す

color-mix() 関数は、以前からご要望の多かった機能を提供します。これは、不透明な色の値を保持しながら、それらの値に透明度を追加する機能です。ブランドカラー変数を使用して、さまざまな不透明度でさまざまな色のバリエーションを作成できます。これを行うには、色を透明色と混合します。ブランドカラーの青と透明度 10% を混ぜると、ブランドカラーは 90% 不透明になります。これにより、カラーシステムを迅速に構築できることがおわかりいただけると思います。

Chrome DevTools で、[スタイル] ペインに便利なプレビュー ベン図のアイコンが表示されるようになりました。

ベン図のカラーミックス アイコンが表示された DevTools のスクリーンショット

その他の例と詳細については、color-mix に関するブログ投稿をご覧になるか、こちらの color-mix() playgroundをお試しください。

CSS の基礎

ユーザーに明らかなメリットをもたらす新機能を構築することも重要ですが、Chrome に搭載される機能の多くは、デベロッパー エクスペリエンスを向上させ、より信頼性が高く整理された CSS アーキテクチャを作成することを目標としています。たとえば、CSS ネスト、カスケード レイヤ、スコープ スタイル、三角関数、個々の変換プロパティなどがあります。

ネスト

対応ブラウザ

  • 120
  • 120
  • 117
  • 17.2

ソース

CSS のネストは Sass の間で人気の機能です。CSS デベロッパーの何年にもわたってリクエストの多いものが、いよいよウェブ プラットフォームに導入されます。ネストを使用すると、より簡潔でグループ化された形式で記述できるようになり、冗長性が軽減されます。

.card {}
.card:hover {}

/* can be done with nesting like */
.card {
  &:hover {

  }
}

また、メディアクエリをネストすることもできます。つまり、コンテナクエリをネストすることもできます。次の例では、コンテナに十分な幅がある場合に、カードが縦向きレイアウトから横向きレイアウトに変更されます。

.card {
  display: grid;
  gap: 1rem;

  @container (width >= 480px) {
    display: flex;
  }
}

flex へのレイアウト調整は、コンテナのインライン スペースの空き容量が 480px 以上になると行われます。条件が満たされると、ブラウザは新しい表示スタイルを適用します。

詳細と例については、CSS のネストに関する投稿をご覧ください。

レイヤをカスケード

対応ブラウザ

  • 99
  • 99
  • 97
  • 15.4

ソース

Google が特定したもう一つの課題は、スタイルが他のスタイルより優先される一貫性を確保することです。この問題を解決するために、CSS カスケードをより適切に制御できるようになりました。

カスケード レイヤは、ユーザーがどのレイヤよりどのレイヤを優先するかを制御できるようにすることで、この問題を解決します。つまり、スタイルを適用するタイミングをより細かく制御できます。

カスケードのイラスト

Codepen プロジェクトのスクリーンショット
Codepen のプロジェクトを確認する。

カスケード レイヤの使用方法について詳しくは、こちらの記事をご覧ください。

スコープ CSS

対応ブラウザ

  • 118
  • 118
  • x
  • 17.4

CSS スコープのスタイルを使用すると、デベロッパーは特定のスタイルが適用される境界を指定できます。これにより、基本的には CSS でネイティブの名前空間を作成できます。以前は、クラス名の変更にサードパーティのスクリプトを使用したり、スタイルの競合を防ぐために特定の命名規則を使用していましたが、まもなく @scope を使用できるようになりました。

ここでは、.title 要素のスコープを .card に設定しています。これにより、そのタイトル要素がページの他の .title 要素(ブログ投稿のタイトルや他の見出しなど)と競合することを防止できます。

@scope (.card) {
  .title {
    font-weight: bold;
  }
}

次のライブデモでは、スコープ制限のある @scope@layer を確認できます。

デモのカードのスクリーンショット

@scope の詳細については、css-cascade-6 仕様をご覧ください。

三角関数

対応ブラウザ

  • 111
  • 111
  • 108
  • 15.4

ソース

CSS の新しい構成要素として、既存の CSS 数学関数に三角関数が追加されています。これらの機能は現在、すべての最新ブラウザで安定版となり、ウェブ プラットフォームでよりオーガニックなレイアウトを作成できるようになっています。この放射状のメニュー レイアウトはその好例です。sin() 関数と cos() 関数を使用して、デザインとアニメーション化が可能になりました。

下のデモでは、点が中心点の周りを回っています。各ドットをその中心を中心として回転させて外側に移動する代わりに、各ドットを X 軸と Y 軸で平行移動します。X 軸と Y 軸の距離は、--anglecos()sin() を考慮して、それぞれ決定されます。

このトピックについて詳しくは、三角関数に関する記事をご覧ください。

個々の変換プロパティ

対応ブラウザ

  • 104
  • 104
  • 72
  • 14.1

ソース

デベロッパーのエルゴノミクスは、個々の変換関数によって向上し続けています。前回 I/O を開催して以来、最新のすべてのブラウザで個々の変換が安定しています。

これまでは、transform 関数を使用してサブ関数を適用し、UI 要素のスケーリング、回転、移動を行っていました。これには多くの繰り返しが必要であり、特にアニメーションの異なるタイミングで複数の変換を適用するときにイライラしました。

.target {
  transform: translateX(50%) rotate(30deg) scale(1.2);
}

.target:hover {
  transform: translateX(50%) rotate(30deg) scale(2); /* Only scale changed here, yet you have to repeat all other parts */
}

今後は、変換のタイプを分離して個別に適用することで、CSS アニメーションでこうした詳細をすべて利用できるようになります。

.target {
  translate: 50% 0;
  rotate: 30deg;
  scale: 1.2;
}

.target:hover {
  scale: 2;
}

これにより、移動、回転、スケールの変化が、アニメーション中の異なる時間のさまざまな変化率で同時に発生する可能性があります。

詳しくは、個々の変換関数に関する投稿をご覧ください。

カスタマイズ可能なコンポーネント

ウェブ プラットフォームを通じて主要なデベロッパーのニーズを解決するために、Google は OpenUI コミュニティ グループと協力して、開始すべき次の 3 つのソリューションを特定しました。

  1. イベント ハンドラ、宣言型 DOM 構造、アクセス可能なデフォルトを備えた組み込みのポップアップ機能。
  2. アンカーの配置を可能にするために、2 つの要素を互いにテザリングする CSS API。
  3. 選択範囲のコンテンツのスタイルを設定する場合に使用する、カスタマイズ可能なプルダウン メニュー コンポーネント。

ポップオーバー

Popover API は、要素に次のような組み込みのブラウザ サポート マジックを提供します。

  • 最上位レイヤをサポートしているため、z-index を管理する必要はありません。ポップオーバーやダイアログを開くと、その要素をページ上部の特別なレイヤにプロモートすることになります。
  • auto ポップオーバーでのライト - 消去動作(無料)により、要素の外側をクリックするとポップオーバーが閉じられ、ユーザー補助ツリーから削除され、フォーカスが適切に管理されるようになりました。
  • ポップオーバーのターゲットの結合組織とポップオーバー自体のデフォルトのユーザー補助です。

つまり、この機能をすべて作成し、これらすべての状態を追跡するために、JavaScript を記述する必要がなくなります。

ポップオーバーの例

ポップオーバーの DOM 構造は宣言型であるため、ポップオーバー要素に id 属性と popover 属性を指定するのと同じように記述できます。次に、その ID を、ポップオーバーを開く要素(popovertarget 属性を持つボタンなど)に同期します。

<div id="event-popup" popover>
  <!-- Popover content goes in here -–>
</div>

<button popovertarget="event-popup">Create New Event</button>

popoverpopover=auto の省略形です。popover=auto を指定した要素は、開いたときに他のポップオーバーを強制的に閉じます。開いたときにフォーカスを受け、ライトを消すこともできます。逆に、popover=manual 要素は他の要素タイプを強制終了せず、すぐにフォーカスを受けず、ライト非表示も行われません。切り替えボタンまたはその他の閉じる操作で閉じることができます。

ポップオーバーに関する最新のドキュメントは、現在 MDN でご覧いただけます。

アンカーの位置

ポップオーバーはダイアログやツールチップなどの要素でも頻繁に使用され、通常は特定の要素に固定する必要があります。このイベントの例を見てみましょう。カレンダーの予定をクリックすると、クリックした予定の近くにダイアログが表示されます。カレンダー アイテムがアンカーで、ポップオーバーは予定の詳細を表示するダイアログです。

anchor() 関数を使用して、中央のツールチップを作成できます。アンカーからの幅を使用して、ツールチップをアンカーの x 位置の 50% に配置できます。次に、既存の配置値を使用して、残りのプレースメント スタイルを適用します。

しかし、ポップオーバーの位置がビューポートに収まらない場合はどうなるでしょうか。

ポップオーバーがビューポートからポップオーバーする

この問題を解決するために、アンカー ポジショニング API には、カスタマイズ可能なフォールバック位置が含まれています。次の例では、「上から下へ」という代替位置を作成しています。ブラウザはまずツールチップを上部に配置し、それがビューポートに収まらない場合は、アンカー要素の下の下部に配置します。

.center-tooltip {
  position-fallback: --top-then-bottom;
  translate: -50% 0;
}

@position-fallback --top-then-bottom {
  @try {
    bottom: calc(anchor(top) + 0.5rem);
    left: anchor(center);
  }

  @try {
    top: calc(anchor(bottom) + 0.5rem);
    left: anchor(center);
  }
}

アンカーの配置について詳しくは、こちらのブログ投稿をご覧ください。

<selectmenu>

ポップオーバーとアンカーの位置の両方を使用して、自由にカスタマイズできる選択メニューを作成できます。OpenUI コミュニティ グループでは、これらのメニューの基本構造を調査し、メニュー内のコンテンツをカスタマイズできるようにする方法を探しています。次の画像の例をご覧ください。

選択メニューの例

左端の selectmenu の例を作成するには、カレンダーの予定に表示される色に対応する色のドットを使用します。

<selectmenu>
  <button slot="button" behavior="button">
    <span>Select event type</span>
    <span behavior="selected-value" slot="selected-value"></span>
    <span><img src="icon.svg"/></span>
  </button>
  <option value="meeting">
    <figure class="royalblue"></figure>
    <p>Meeting</p>
  </option>
  <option value="break">
    <figure class="gold"></figure>
     <p>Lunch/Break</p>
  </option>
  ...
</selectmenu>

個別のプロパティ遷移

ポップオーバーの入出力をすべてスムーズに行うには、ウェブで個別のプロパティをアニメーション化するなんらかの方法が必要です。最上位レイヤとのアニメーション化、display: none との間のアニメーション化など、これまで通常はアニメーション化できなかったプロパティがあります。

ポップオーバー、選択メニュー、さらにはダイアログやカスタム コンポーネントなどの既存の要素も適切に遷移できるようにする取り組みの一環として、ブラウザでこれらのアニメーションをサポートする新しいパイプラインが実現されています。

次のポップオーバーのデモでは、開いた状態に :popover-open、起動前と開いた状態に @starting-style を使用して、ポップオーバーの入出力をアニメーション化しています。また、展開後の状態については、要素に変換値を直接適用しています。これをディスプレイで機能させるには、次のように transition プロパティに追加する必要があります。

.settings-popover {
  &:popover-open {
    /*   0. before-change   */
    @starting-style {
      transform: translateY(20px);
      opacity: 0;
    }

    /*   1. open (changed) state   */
    transform: translateY(0);
    opacity: 1;
  }

  /*   2. After-change state */
  transform: translateY(-50px);
  opacity: 0;

  /*  enumarate transitioning properties, including display */
  transition: transform 0.5s, opacity 0.5s, display 0.5s allow-discrete;
}

インタラクション数

ウェブ UI 機能の説明の最後のステップであるインタラクションについて説明します。

個別のプロパティのアニメーション化についてはすでに説明しましたが、スクロールドリブン アニメーションやビュー遷移に関する、Chrome の魅力的な API もあります。

スクロールドリブン アニメーション

対応ブラウザ

  • 115
  • 115
  • x

ソース

スクロールドリブン アニメーションを使用すると、スクロール コンテナのスクロール位置に基づいてアニメーションの再生を制御することができます。つまり、上下にスクロールすると、アニメーションが前方または後方にスクラブされます。また、スクロールドリブン アニメーションを使用すると、スクロール コンテナ内の要素の位置に基づいてアニメーションを制御することもできます。これにより、視差効果のある背景画像、スクロールの進行状況バー、ビューに入ったときに出現する画像など、面白い視覚効果を作成することができます。

この API は一連の JavaScript クラスと CSS プロパティをサポートしており、宣言型のスクロールドリブン アニメーションを簡単に作成できます。

スクロールによって CSS アニメーションを動作させるには、新しい scroll-timeline プロパティ、view-timeline プロパティ、animation-timeline プロパティを使用します。JavaScript Web Animations API を動作させるには、ScrollTimeline または ViewTimeline のインスタンスを timeline オプションとして Element.animate() に渡します。

これらの新しい API は、既存の Web Animations API や CSS Animations API と連携して機能するため、これらの API のメリットを活用できます。これには、これらのアニメーションをメインスレッド外で実行させる機能が含まれます。ぜひご一読ください。数行のコードを追加するだけで、スクロールによって滑らかなアニメーションを実現し、メインスレッドから実行できるようになりました。嫌いなものは?!

このようなスクロールドリブン アニメーションの作成方法について詳しくは、スクロールドリブン アニメーションに関するこちらの記事をご覧ください。

切り替え効果を表示

対応ブラウザ

  • 111
  • 111
  • x
  • x

ソース

View Transition API を使用すると、1 つのステップで DOM を簡単に変更でき、2 つの状態間の遷移をアニメーションで作成できます。ビュー間を簡単にフェードアウトできますが、ページの個々の部分をどのように移行するかを制御することもできます。

ビュー遷移はプログレッシブ エンハンスメントとして使用できます。任意のメソッドで DOM を更新するコードを取得し、ビュー遷移 API でラップして、この機能をサポートしていないブラウザ用のフォールバックを提供します。

function spaNavigate(data) {
  // Fallback for browsers that don't support this API:
  if (!document.startViewTransition) {
    updateTheDOMSomehow(data);
    return;
  }

  // With a transition:
  document.startViewTransition(() => updateTheDOMSomehow(data));
}

遷移の見た目は CSS で制御

@keyframes slide-from-right {
  from { opacity: 0; transform: translateX(75px); }
}

@keyframes slide-to-left {
  to { opacity: 0; transform: translateX(-75px); }
}

::view-transition-old(root) {
  animation: 350ms both slide-to-left ease;
}

::view-transition-new(root) {
  animation: 350ms both slide-from-right ease;
}

Maxi Ferreira によるこの素晴らしいデモで示されているように、ビュー遷移が行われている間も、他のページ操作(動画の再生など)は動作し続けます。

現在、ビュー遷移は Chrome 111 以降のシングルページ アプリ(SPA)で動作します。複数ページのアプリについては、現在対応中です。詳しくは、ビューの移行に関するガイドをご覧ください。

おわりに

developer.chrome.com で、CSS と HTML に関する最新の情報をご確認ください。その他のウェブ ランディングについては、I/O 動画をご覧ください。