CSS とウェブ UI の最新情報: I/O 2024 のまとめ

ウェブ プラットフォームはイノベーションに満ちており、このエキサイティングな進化の最前線にいたのが CSS とウェブ UI の機能です。ウェブ UI はまさに黄金期を迎えています。これまでにないスピードで新しい CSS 機能がブラウザに導入され、美しく魅力的なウェブ エクスペリエンスを作成するための可能性が広がっています。このブログ投稿では、CSS の現状を詳しく掘り下げ、ウェブ アプリケーションの構築方法を再定義する、ゲームチェンジャーとなる新機能の一部をご紹介します。これらの新機能は、Google I/O 2024 でライブ配信されました。

斬新なインタラクティブ エクスペリエンス

ウェブ エクスペリエンスとは、基本的には、ユーザーとユーザーとのやり取りです。そのため、質の高いユーザー インタラクションに投資することは非常に重要です。Google は、ウェブページ内の移動やウェブページ間の移動に関して、ウェブ上でこれまでにない機能を実現する大幅な改善に取り組んできました。

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

対応ブラウザ

  • Chrome: 115。
  • Edge: 115。
  • Firefox: フラグの背後。
  • Safari: サポートされていません。

ソース

名前が示すように、スクロールドリブン アニメーション API を使用すると、スクロール オブザーバーやその他の負荷の高いスクリプトに依存することなく、動的なスクロールベースのアニメーションを作成できます。

スクロールドリブン アニメーションを作成する

プラットフォームで時間ベースのアニメーションが機能する仕組みと同様に、スクロールのスクロール進行状況を使用してアニメーションを開始、一時停止、逆再生できるようになりました。そのため、前方にスクロールするとアニメーションが進行し、後方にスクロールすると逆の方向に進みます。これにより、ビューポート内やビューポート内でアニメーション化される要素を使用して、部分的なビジュアルやフルページのビジュアルを作成できます。これはスクロールテリングとも呼ばれ、ダイナミックな視覚効果を生み出します。

スクロール ドリブンのアニメーションは、重要なコンテンツをハイライト表示したり、ストーリーをユーザーに案内したり、ウェブページに動的なタッチを加えたりするのに使用できます。

スクロール駆動型アニメーションのビジュアル

ライブデモ

@keyframes appear {
  from {
    opacity: 0;
    scale: 0.8;
  }
  to {
    opacity: 1;
    scale: 1;
  }
}

img {
  animation: appear linear;
  animation-timeline: view();
  animation-range: entry 25% cover 50%;
}

上記のコードは、画像の不透明度とスケールを変更してビューポートに表示されるシンプルなアニメーションを定義しています。アニメーションはスクロール位置によって駆動されます。このエフェクトを作成するには、まず CSS アニメーションを設定してから、animation-timeline を設定します。この場合、view() 関数はデフォルト値の状態で、スクロールポート(この例ではビューポート)を基準として画像を追跡します。

特にユーザー補助機能のニーズについては、ブラウザのサポートとユーザー設定に留意することが重要です。したがって、@supports ルールを使用して、ブラウザがスクロール ドリブン アニメーションをサポートしているかどうかを確認し、スクロール ドリブン アニメーションを @media (prefers-reduced-motion: no-preference) などのユーザー設定クエリでラップして、ユーザーのモーション設定を尊重します。これらのチェックを行うことで、スタイルが機能し、アニメーションがユーザーにとって問題にならないことが確認できます。

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    /* Apply scroll-driven animations here */
  }
}

スクロール ドリブンのアニメーションには、全ページのスクロール ナレーション エクスペリエンスが含まれる場合もありますが、ウェブアプリをスクロールする際にヘッダーバーが最小化され、シャドウが表示されるなど、より微妙なアニメーションが含まれる場合もあります。

スクロールドリブン アニメーションのビジュアル

ライブデモ

@keyframes shrink-name {
  from {
    font-size: 2em;
  }
  to {
    font-size: 1.5em;
  }
}

@keyframes add-shadow {
  from {
    box-shadow: none;
  }
  to {
    box-shadow: 0 4px 2px -2px gray;
  }
}

header {
  animation: add-shadow linear both;
}

h2 {
  animation: shrink-name linear both;
}

header, h2 {
  animation-timeline: scroll();
  animation-range: 0 150px;
}

このデモでは、ヘッダー、テキスト、ナビゲーション バー、背景など、いくつかの異なるキーフレーム アニメーションを使用し、それぞれにスクロール駆動アニメーションを適用しています。それぞれにアニメーション スタイルは異なりますが、アニメーション タイムライン、最も近いスクローラー、アニメーション範囲は同じで、ページの最上部から 150 ピクセルまですべて同じです。

スクロール ドリブン アニメーションのパフォーマンス上のメリット

この組み込み API を使用すると、作成したカスタム スクリプトや追加のサードパーティ依存関係など、メンテナンスする必要があるコードの負担を軽減できます。また、さまざまなスクロール オブザーバーを用意する必要がなくなるため、パフォーマンスが大幅に向上します。これは、CSS で新しい API を直接使用する場合でも、JavaScript フックを使用する場合でも、コンポジタでアニメーション化できるプロパティ(変形や不透明度など)をアニメーション化するときに、スクロール ドリブン アニメーションがメインスレッドで動作するためです。

Tokopedia は最近、スクロールドリブン アニメーションを使用して、スクロール時にプロダクトのナビゲーション バーが表示されるようにしました。この API を使用すると、コード管理とパフォーマンスの両面で大きなメリットがあります。

Tokopedia のこの商品ナビゲーション バーは、スクロールに応じてアニメーションで動きます。

「従来の JS スクロール イベントを使用する場合と比較して、コード行数を最大 80% 削減できました。また、スクロール中の平均 CPU 使用率が 50% から 2% に低下しました。- Tokopedia、シニア ソフトウェア エンジニア Andy Wihalim 氏

スクロール エフェクトの今後

こうした効果により、ウェブはさらに魅力的な場所になるでしょう。Google はすでに、次に何をすべきかについて検討しています。これには、新しいアニメーション タイムラインを使用するだけでなく、スクロールポイントを使用してアニメーションの開始をトリガーする機能(スクロール トリガー アニメーション)も含まれます。

今後、ブラウザにさらに多くのスクロール機能が追加される予定です。次のデモは、これらの今後の機能の組み合わせを示しています。CSS scroll-start-target を使用して選択ツール内の最初の日時を設定し、JavaScript scrollsnapchange イベントを使用してヘッダーの日付を更新することで、データをスナップされたイベントと簡単に同期できます。

Codepen でライブデモを見る

この機能に基づいて、JavaScript の scrollsnapchanging イベントを使用して選択ツールをリアルタイムで更新することもできます。

これらの機能は現在、フラグが設定された Canary 版でのみ利用できます。しかし、これまでプラットフォームで構築が不可能だった、または非常に困難だった機能を実現し、スクロールベースのインタラクションの将来の可能性を示しています。

スクロール ドリブン アニメーションの使い方について詳しくは、Chrome for Developers YouTube チャンネルで公開されている新しい動画シリーズをご覧ください。この動画では、Bramus Van Damme がスクロール ドリブン アニメーションの基本について説明します。この機能の仕組み、用語、さまざまなエフェクトの作成方法、エフェクトを組み合わせて豊かなエクスペリエンスを構築する方法などについて学びます。ぜひご覧ください。

遷移を表示する

ここまで、ウェブページ内でアニメーション化する優れた新機能について説明しましたが、ページビュー間のアニメーションでシームレスなユーザー エクスペリエンスを実現するビュー遷移という強力な新機能も追加しました。ビュー遷移により、ウェブに新たなレベルの流動性がもたらされ、単一ページ内の異なるビュー間、または異なるページ間でのシームレスな移行を実現できます。

対応ブラウザ

  • Chrome: 111.
  • Edge: 111。
  • Firefox: サポートされていません。
  • Safari: 18。

ソース

Airbnb は、スムーズでシームレスなウェブ ナビゲーション エクスペリエンスを実現するために、ビュー遷移を UI に統合するテストをすでに行っています。たとえば、リスティング エディタのサイドバーから、写真の編集や設備の追加まで、すべて滑らかなユーザーフローの中で行えます。

Airbnb で見られるような、同じドキュメント内のビューの遷移。
Maxwell Barvian のポートフォリオ。ビュー間のビュー遷移を紹介します。

こうしたページ全体への効果は美しくシームレスですが、ミクロ インタラクションを作成することもできます。この例では、ユーザーの操作に応じてリストビューが更新される例です。この効果は、ビュー遷移によって簡単に実現できます。

シングルページ アプリケーションでビュー遷移をすばやく有効にする方法は、document.startViewTransition を使用してインタラクションをラップし、遷移する各要素に view-transition-name をインラインで設定するか、DOM ノードを作成するときに JavaScript を使用して動的に設定するだけです。

デモのビジュアル

ライブデモ

document.querySelectorAll('.delete-btn').forEach(btn => {
  btn.addEventListener('click', () => {
    document.startViewTransition(() => {
      btn.closest('.card').remove();
    });
  })
});
/* Styles for the transition animation */
::view-transition-old(.card):only-child {
  animation: fade-out ease-out 0.5s;
}

遷移クラスを表示する

ビュー遷移名を使用すると、ビュー遷移にカスタム アニメーションを適用できますが、要素が多数遷移する場合は煩雑になる可能性があります。今年のビュー遷移の最初の新機能アップデートでは、この問題を簡素化し、カスタム アニメーションに適用できるビュー遷移クラスを作成できるようになりました。

対応ブラウザ

  • Chrome: 125。
  • エッジ: 125。
  • Firefox: サポートされていません。
  • Safari Technology Preview: サポートされています。

切り替え効果の種類を表示する

ビュー遷移の大きな改善点として、ビュー遷移の種類のサポートがあります。ビュー遷移タイプは、ページビューとの間でアニメーション化するときに、視覚的なビュー遷移を別の種類にしたい場合に便利です。

対応ブラウザ

  • Chrome: 125.
  • エッジ: 125。
  • Firefox: サポートされていません。
  • Safari: 18。

たとえば、ホームページからブログ ページへのアニメーションと、ブログ ページからホームページへのアニメーションを別々に設定できます。または、この例のように、左から右、右から左など、さまざまな方法でページを切り替えることもできます。以前は、この処理は面倒でした。DOM にクラスを追加してスタイルを適用し、その後でクラスを削除する必要がありました。View-transition-types を使用すると、新しい遷移を開始する前に手動で古い遷移をクリーンアップする必要がなくなります。ブラウザが自動的にクリーンアップします。

ページネーションのデモの録画。タイプによって、使用するアニメーションが決まります。有効な遷移タイプにより、スタイルシート内でスタイルが分離されます。

document.startViewTransition 関数内で型を設定できるようになりました。この関数はオブジェクトを受け取れるようになりました。update は DOM を更新するコールバック関数で、types は型を含む配列です。

document.startViewTransition({
  update: myUpdate,
  types: ['slide', 'forwards']
})

複数ページ ビューの切り替え

ウェブの強みは、その広範さにあります。多くのアプリケーションは、単なるシングルページではなく、複数のページを含む堅牢なタペストリーです。そこで、Chromium 126 でマルチページ アプリケーションのドキュメント間のビュー遷移のサポートをリリースすることをお知らせいたします。

対応ブラウザ

  • Chrome: 126。
  • Edge: 126。
  • Firefox: サポートされていません。
  • Safari Technology Preview: サポートされています。

この新しいクロスドキュメント機能セットには、web.dev から web.dev/blog に移動するなど、同じオリジン内に存在するウェブ エクスペリエンスが含まれますが、web.dev から blog.web.dev に移動する、または google.com などの別のドメインに移動するなど、クロスオリジンの移動は含まれません。

同一ドキュメント ビュー遷移の主な違いの 1 つは、遷移を document.startViewTransition() でラップする必要がないことです。代わりに、CSS の @view-transition アットルールを使用して、ビュー遷移に関与する両方のページをオプトインします。

@view-transition {
  navigation: auto;
}

よりカスタマイズされた効果を得るには、新しい pageswap イベント リスナーまたは pagereveal イベント リスナーを使用して JavaScript をフックします。これにより、ビュー遷移オブジェクトにアクセスできます。

pageswap を使用すると、古いスナップショットを取得する直前に送信ページの土壇場での変更を行うことができます。pagereveal を使用すると、初期化後に新しいページのレンダリングを開始する前に、新しいページをカスタマイズできます。

window.addEventListener('pageswap', async (e) => {
    // ...
});

window.addEventListener('pagereveal', async (e) => {
    // ...
});
マルチページ アプリでビュー遷移を表示。デモリンクをご覧ください。

今後、以下のビュー遷移を拡張する予定です。

  • スコープ切り替え: DOM サブツリーへの遷移を制限して、ページの他の部分も引き続きインタラクティブにし、複数のビュー遷移を同時に実行できます。
  • ジェスチャー ドリブンのビュー遷移: ドラッグやスワイプなどのジェスチャーを使用して、ドキュメント間のビュー遷移をトリガーし、ウェブ上でネイティブに近いエクスペリエンスを実現できます。
  • CSS でのナビゲーション マッチング: JavaScript で pageswap イベントと pagereveal イベントを使用する代わりに、CSS で直接クロスドキュメント ビュー トランジションをカスタマイズします。マルチページ アプリケーションのビュー トランジションの詳細(プリレンダリングで最もパフォーマンスの高い設定方法など)については、Bramus Van Damme による次の講演をご覧ください。

エンジン対応の UI コンポーネント: 複雑な操作を簡素化

複雑なウェブ アプリケーションの構築は簡単ではありませんが、CSS と HTML は進化しており、このプロセスをより管理しやすくしています。新機能と機能強化により、UI コンポーネントの作成が簡素化され、優れたエクスペリエンスの構築に集中できます。これは、CSS ワーキング グループ、Open UI コミュニティ グループ、WHATWG(Web Hypertext Application Technology Working Group)など、複数の主要な標準化団体とコミュニティ グループが協力して行っています。

開発者が抱える大きな課題の 1 つは、一見シンプルなリクエストとして、プルダウン メニュー(select 要素)のスタイルを設定できることです。表面的には単純な問題に見えますが、レイアウトとレンダリングから、スクロールと操作、ユーザー エージェントのスタイル設定と CSS プロパティ、さらには HTML 自体の変更に至るまで、プラットフォームの多くの部分に影響する複雑な問題です。

オプション、トリガーボタン、インジケーター矢印、選択したオプションを含むオプションのデータリストで選択します。
選択内容の分解

プルダウンは多くの要素で構成されており、次のような多くの状態を考慮する必要があります。

  • キーボード バインディング(インタラクションの開始/終了)
  • クリックして閉じる
  • アクティブなポップオーバーの管理(1 つのポップオーバーを開くと他のポップオーバーを閉じる)
  • タブのフォーカス管理
  • 選択したオプション値を可視化しています
  • 矢印インタラクション スタイル
  • 状態管理(開く/閉じる)

現在、これらの状態をすべて自分で管理するのは困難ですが、プラットフォームでも簡単に管理できるわけではありません。この問題を解決するため、これらの要素を分割し、プルダウンのスタイル設定を可能にするだけでなく、さらに多くのことを可能にするプリミティブな機能をいくつかリリースしました。

Popover API

まず、popover というグローバル属性をリリースしました。この属性は、数週間前にベースラインの「新規利用可能」ステータスに達しました。

対応ブラウザ

  • Chrome: 114。
  • Edge: 114.
  • Firefox: 125.
  • Safari: 17。

ソース

ポップオーバー要素は、ボタンなどの起動元または JavaScript で開かれるまで display: none で非表示になります。基本的なポップオーバーを作成するには、要素に popover 属性を設定し、popovertarget を使用してその ID をボタンにリンクします。ボタンが起動元になり

デモのビジュアル

ライブデモ

<button popovertarget="my-popover">Open Popover</button>

<div id="my-popover" popover>
  <p>I am a popover with more information.</p>
</div>

ポップオーバー属性が有効になったことで、ブラウザは追加のスクリプトなしで次のような多くの重要な動作を処理できるようになりました。

  • 最上位レイヤへのプロモーション: ページの残りの部分の上に別個のレイヤがあるため、z-index を操作する必要はありません。
  • ライトを消す機能: ポップオーバー領域の外側をクリックすると、ポップオーバーが閉じてフォーカスが戻ります。
  • デフォルトのタブ フォーカス管理: ポップオーバーを開くと、次のタブストップがポップオーバー内に表示されます。
  • 組み込みのキーボード バインディング。esc キーを押すか、ダブルタップするとポップオーバーが閉じてフォーカスが戻ります。
  • デフォルトのコンポーネント バインディング。: ブラウザは、ポップオーバーをトリガーに意味的に関連付けます。
GitHub のホーム画面
GitHub ホームページのメニュー。

今日では、気づかずにこのポップオーバー API を使用しているかもしれません。GitHub は、ホームページの [新規] メニューと pull リクエストのレビュー概要にポップオーバーを実装しました。Oddbird が開発したポップオーバー ポリフィルを使用してこの機能を段階的に強化し、GitHub 独自の Keith Cirkel のサポートを受けて古いブラウザもサポートしました。

「ポップオーバーに移行することで、文字どおり数千行のコードを廃止できました。ポップオーバーは、魔法の z インデックス番号との戦いを回避するのに役立ちます。宣言型のボタン動作で適切なユーザー補助ツリー関係を確立し、フォーカス動作を組み込むことで、デザインシステムでパターンを正しく実装することが大幅に容易になります。-Keith Cirkel、ソフトウェア エンジニア、GitHub」

開始時と終了時のエフェクトをアニメーション化する

ポップオーバーを使用する場合は、インタラクションを追加することをおすすめします。ポップオーバーのアニメーションをサポートするために、昨年4 つの新しいインタラクション機能が導入されました。次のようなアクセサリーが含まれます。

キーフレーム タイムラインで displaycontent-visibility をアニメーション化する機能。

transition-behavior プロパティと allow-discrete キーワードを使用して、display などの離散プロパティの遷移を有効にします。

対応ブラウザ

  • Chrome: 117。
  • Edge: 117.
  • Firefox: 129.
  • Safari: 17.4。

ソース

display: none から最上位レイヤへの入口の効果をアニメーション化する @starting-style ルール。

対応ブラウザ

  • Chrome: 117。
  • Edge: 117.
  • Firefox: 129.
  • Safari: 17.5。

ソース

アニメーション中のトップレイヤの動作を制御するオーバーレイ プロパティ。

対応ブラウザ

  • Chrome: 117。
  • Edge: 117.
  • Firefox: サポートされていません。
  • Safari: サポートされていません。

ソース

これらのプロパティは、ポップオーバーやダイアログなど、最上位レイヤにアニメーション化する要素に適用できます。バックドロップのあるダイアログの場合、全体は次のようになります。

デモのビジュアル

ライブデモ

dialog, ::backdrop{
  opacity: 0;
  transition: opacity 1s, display 1s allow-discrete, overlay 1s allow-discrete;
}

[open], [open]::backdrop {
  opacity: 1;
}

@starting-style {
  [open], [open]::backdrop {
    opacity: 0;
  }
}

まず、@starting-style を設定して、ブラウザがこの要素を DOM にアニメーション化するスタイルを認識できるようにします。これは、ダイアログとバックドロップの両方で行われます。次に、ダイアログと背景の両方の開いた状態のスタイルを設定します。ダイアログの場合は open 属性を使用し、ポップオーバーの場合は ::popover-open 疑似要素を使用します。最後に、allow-discrete キーワードを使用して opacitydisplayoverlay をアニメーション化し、離散プロパティを遷移できるアニメーション モードを有効にします。

アンカーの配置

ポップオーバーは、物語の始まりにすぎません。注目すべきアップデートとして、Chrome 125 からアンカーの配置がサポートされるようになりました。

対応ブラウザ

  • Chrome: 125.
  • エッジ: 125。
  • Firefox: サポートされていません。
  • Safari: サポートされていません。

ソース

アンカー ポジショニングを使用すると、数行のコードで、配置された要素を 1 つ以上のアンカー要素に固定するロジックをブラウザで処理できます。次の例では、各ボタンにアンカーされたシンプルなツールチップが下部の中央に配置されています。

デモのビジュアル

ライブデモ

アンカー要素(この場合はボタン)の anchor-name プロパティと、配置された要素(この場合はツールチップ)の position-anchor プロパティを使用して、CSS でアンカー配置の関係を設定します。次に、anchor() 関数を使用して、アンカーに対する絶対位置または固定位置を適用します。次のコードでは、ツールチップの上部がボタンの下部に配置されます。

.anchor {
  anchor-name: --my-anchor;
}

.positioned {
  position: absolute;
  position-anchor: --my-anchor;
}

または、アンカー関数でアンカー名を直接使用し、position-anchor プロパティをスキップします。これは、複数の要素にアンカーを設定する場合に便利です。

.anchor {
  anchor-name: --my-anchor;
}

.positioned {
  position: absolute;
  top: anchor(--my-anchor bottom);
}

最後に、justify プロパティと align プロパティに新しい anchor-center キーワードを使用して、配置された要素をアンカーの中央に配置します。

.anchor {
  anchor-name: --my-anchor;
}

.positioned {
  position: absolute;
  top: anchor(--my-anchor bottom);
  justify-self: anchor-center;
}

ポップオーバーでアンカーの位置指定を使用すると非常に便利ですが、ポップオーバーはアンカーの位置指定を使用する場合に必須ではありません。アンカーの位置は、任意の 2 つ(またはそれ以上)の要素とともに使用して、視覚的な関係を作成できます。実際、次のデモは Roman Komarov の記事を参考にしており、リストアイテムにカーソルを合わせたりタブで移動したりすると、アンダーライン スタイルがリストアイテムに固定されます。

デモのビジュアル

ライブデモ

この例では、アンカー関数を使用して、leftrightbottom の物理プロパティを使用してアンカー位置を設定します。いずれかのリンクにカーソルを合わせると、ターゲット アンカーが変更され、ブラウザがターゲットを移動して配置を適用します。同時に色もアニメーション化され、きれいな効果が得られます。

ul::before {
  content: "";
  position: absolute;
  left:   anchor(var(--target) left);
  right:  anchor(var(--target) right);
  bottom: anchor(var(--target) bottom);
  ...
}

li:nth-child(1) { --anchor: --item-1 }
ul:has(:nth-child(1) a:is(:hover, :focus-visible)) {
  --target: --item-1;
  --color: red;
}

inset-area の配置

これまで使用していたデフォルトの方向指定絶対配置に加えて、アンカー配置 API の一部として、新しいレイアウト メカニズム(インセット領域)が導入されています。インセット領域を使用すると、配置された要素をそれぞれのアンカーに対して簡単に配置できます。アンカー要素が中央にある 9 セルのグリッドで機能します。たとえば、inset-area: top は配置された要素を一番上に配置し、inset-area: bottom は配置された要素を一番下に配置します。

最初のアンカーのデモを簡素化すると、inset-area を使用して次のように表示されます。

.anchor {
  anchor-name: --my-anchor;
}

.positioned {
  position: absolute;
  position-anchor: --my-anchor;
  inset-area: bottom;
}

これらの位置値を span キーワードと組み合わせて、中央の位置から左、右、またはすべてにまたがって、使用可能な列または行のセット全体を占有するように指定できます。論理プロパティを使用することもできます。このレイアウト メカニズムを簡単に可視化して確認するには、Chrome 125 以降の このツールをご覧ください。

これらの要素はアンカーされているため、アンカーが移動すると、配置された要素はページ内で動的に移動します。この例では、コンテナ クエリ スタイルのカード要素が、その固有のサイズに基づいてサイズ変更されます(これはメディアクエリではできないことです)。また、カード UI が変更されると、アンカー付きメニューが新しいレイアウトに沿って移動します。

デモのビジュアル

ライブデモ

position-try-options を使用した動的なアンカー位置

ポップオーバーとアンカーの位置を組み合わせることで、メニューやサブメニューのナビゲーションをはるかに簡単に作成できます。また、固定された要素が表示されているビューポートの端に達したら、位置の変更をブラウザに処理させることができます。 これを行うにはいくつかの方法があります。1 つ目は、独自のポジショニング ルールを作成することです。この場合、サブメニューは最初は [外観] ボタンの右側に表示されます。ただし、メニューの右側に十分なスペースがない場合は、@position-try ブロックを作成し、カスタム識別子 --bottom を指定できます。次に、position-try-options を使用してこの @position-try ブロックをアンカーに接続します。

これで、ブラウザはこれらのアンカー状態を切り替え、最初に右側の位置を試してから、下部に移動します。これを実現するには、適切な遷移を使用します。

デモのビジュアル

ライブデモ

#submenu {
  position-anchor: --submenu;
  top: anchor(top);
  left: anchor(right);
  margin-left: var(--padding);

  position-try-options: --bottom;

  transition: top 0.25s, left 0.25s;
  width: max-content;
}

@position-try --bottom {
  top: anchor(left);
  left: anchor(bottom);
  margin-left: var(--padding);
}

明示的な配置ロジックに加えて、ブロック方向やインライン方向にアンカーを反転するなど、基本的な操作を行うためのキーワードがブラウザで用意されています。

position-try-options: flip-block, flip-inline;

flip を簡単に行うには、flip キーワード値を利用し、position-try 定義の記述は一切スキップします。これで、数行の CSS で、位置情報に応じてアンカーを配置した要素を完全に機能させることができます。

デモのビジュアル

ライブデモ

.tooltip {
  inset-area: top;
  position-try-options: flip-block;
}

詳しくは、アンカー ポジショニングの使用方法をご覧ください。

多層 UI の未来

テザリング エクスペリエンスはあらゆる場所で見られ、この投稿で紹介した一連の機能は、クリエイティビティを解き放ち、アンカー配置された要素やレイヤ化されたインターフェースをより適切に制御するための優れたスタート地点となります。しかし、これはほんの序章にすぎません。たとえば、現在 popover は、呼び出し元要素としてボタンを使用するか、JavaScript を使用する場合にのみ機能します。Wikipedia スタイルのプレビューなど、ウェブ プラットフォーム全体で使用されているパターンでは、リンクからポップオーバーを操作したり、ユーザーが興味を示した際にポップオーバーをトリガーしたりできるようにする必要があります。この場合、必ずしもクリックする必要はありません(ホバーやタブのフォーカスなど)。

ポップオーバー API の次のステップとして、interesttarget の開発を進めています。これにより、こうしたニーズを解決し、適切なユーザー補助フックを組み込んでこうしたエクスペリエンスを簡単に再現できるようになります。これは解決が難しいユーザー補助の問題であり、理想的な動作に関する多くの未解決の問題がありますが、この機能をプラットフォーム レベルで解決して標準化することで、すべてのユーザーの操作性が向上するはずです。

<a interesttarget="my-tooltip">Hover/Focus to show the tooltip</a>

<span popover=hint id="my-toolip">This is the tooltip</span>

また、Keith Cirkel 氏と Luke Warlow 氏という 2 人のサードパーティ デベロッパーの協力により、将来を見据えた別の一般的な呼び出し元(invoketarget)がカナリアでテストできるようになりました。invoketarget は、<dialog><details><video><input type="file"> など、すべてのインタラクティブ要素に対して正規化されたポップオーバーを popovertarget で提供する宣言型のデベロッパー エクスペリエンスをサポートしています。

<button invoketarget="my-dialog">
  Open Dialog
</button>

<dialog id="my-dialog">
  Hello world!
</dialog>

この API でまだカバーされていないユースケースがあることは認識しています。たとえば、アンカー要素をアンカーに接続する矢印のスタイル設定(特にアンカー要素の位置が変化する場合)、要素が境界ボックスに達したときに設定された別の位置にスナップするのではなく、要素が「スライド」してビューポート内に留まるようにするなどです。そのため、この強力な API のリリースを心待ちにしていたと同時に、今後さらに機能を拡張していくことを楽しみにしています。

スタイル設定可能な選択

チームは popoveranchor を組み合わせて使用し、カスタマイズ可能な選択プルダウンを有効にすることを進めてきました。幸い、この問題は大きく進展しています。残念ながら、この API は現時点ではまだ試験運用版です。ただし、ライブデモや進捗状況の最新情報をお知らせし、皆様からのフィードバックをお待ちしております。まず、ユーザーが新しいカスタマイズ可能な選択機能を有効にする方法が進展しました。現在、この方法は開発中です。CSS の appearance プロパティを使用して、appearance: base-select に設定します。外観を設定すると、カスタマイズ可能な新しい選択機能が有効になります。

select {
  appearance: base-select;
}

appearance: base-select に加えて、HTML もいくつか更新されています。これには、オプションを datalist でラップしてカスタマイズする機能や、オプションに画像などのインタラクティブでない任意のコンテンツを追加する機能が含まれます。また、新しい要素 <selectedoption> にアクセスすることもできます。この要素には、オプションの内容が反映されたあと、必要に応じてカスタマイズできます。この要素はとても便利です。

デモのビジュアル

flag-demo

ライブデモ

<select>
  <button type=popover>
    <selectedoption></selectedoption>
  </button>
  <datalist>
    <option value="" hidden>
      <p>Select a country</p>
    </option>
    <option value="andorra">
      <img src="Flag_of_Andorra.svg" />
      <p>Andorra</p>
    </option>
    <option value="bolivia">
      <img src="Flag_of_Bolivia.svg" />
      <p>Bolivia</p>
    </option>
...
  </datalist>
</select>

次のコードは、Gmail UI で <selectedoption> をカスタマイズする方法を示しています。ここでは、スペースを節約するために、選択した返信の種類を視覚的なアイコンで表しています。selectedoption 内で基本的な表示スタイルを使用すると、オプションのスタイルとプレビューのスタイルを区別できます。この場合、オプションに表示されるテキストは selectedoption で視覚的に非表示にできます。

デモのビジュアル

Gmail のデモ

ライブデモ

selectedoption .text {
  display: none;
}

この API で <select> 要素を再利用する最大のメリットの 1 つは、下位互換性です。この国選択では、ユーザーがコンテンツを簡単に解析できるように、オプションに国旗の画像が付いたカスタマイズされた UI が表示されます。サポートされていないブラウザでは、カスタム ボタン、データリスト、selectedoption、オプション内の画像など、認識できない行は無視されるため、代替手段は現在のデフォルトの選択 UI に似たものになります。

サポートされていないブラウザでは、現在の一部の機能が利用できます。 左がサポートされているブラウザのビジュアル、右がサポートされていないブラウザのフォールバック。

カスタマイズ可能なセレクタを使用すると、可能性は無限大です。Airbnb スタイルの国選択ツールは、レスポンシブ デザインに適した巧みなスタイルが採用されている点が特に気に入っています。今後リリースされるスタイル設定可能なセレクタでは、この機能以外にも多くのことが可能になります。これは、ウェブ プラットフォームに必要不可欠な機能です。

デモのビジュアル

ライブデモ

独占アコーディオン

Chrome チームが注力している UI コンポーネントは、特定のスタイル設定(およびそれに付随するすべての要素)だけではありません。最初の追加コンポーネント更新は、排他的なアコーディオンを作成する機能です。これにより、アコーディオン内のアイテムを一度に 1 つだけ開くことができます。

対応ブラウザ

  • Chrome: 120。
  • エッジ: 120。
  • Firefox: 130。
  • Safari: 17.2。

これを有効にするには、複数の details 要素に同じ名前の値を適用します。これにより、ラジオボタンのグループのように、接続された詳細のグループが作成されます。

限定の折りたたみ式デモ
<details name="learn-css" open>
  <summary>Welcome to Learn CSS!</summary>
</details>

<details name="learn-css">
  <summary>Box Model</summary>
  <p>...</p>
</details>

<details name="learn-css">
  <summary>Selectors</summary>
  <p>...</p>
</details>

:user-valid:user-invalid

UI コンポーネントの改善として、:user-valid:user-invalid の疑似クラスも追加されました。:user-valid 疑似クラスと :user-invalid 疑似クラスは、最近すべてのブラウザで安定しており、:valid 疑似クラスと :invalid 疑似クラスと同様に動作しますが、ユーザーが入力を大幅に操作した後にのみフォーム コントロールと一致します。つまり、フォームの値が操作されたか「変更済み」になったかどうかを判断するために必要なコードが大幅に削減されます。これはユーザー フィードバックの提供に非常に役立ち、これまでこの処理に必要だった大量のスクリプトを削減できます。

対応ブラウザ

  • Chrome: 119.
  • Edge: 119.
  • Firefox: 88。
  • Safari: 16.5。

ソース

スクリーンキャストのデモ

ライブデモ

input:user-valid,
select:user-valid,
textarea:user-valid {
    --state-color: green;
    --bg: linear-gradient(...);
}

input:user-invalid,
select:user-invalid,
textarea:user-invalid {
    --state-color: red;
    --bg: linear-gradient(...);
}

詳しくは、user-* フォーム検証の疑似要素の使用方法をご覧ください。

field-sizing: content

最近リリースされた便利なコンポーネントの更新として、field-sizing: content があります。これは、入力や textarea などのフォーム コントロールに適用できます。これにより、入力の内容に応じて入力のサイズを拡大(または縮小)できます。field-sizing: content は textarea に特に便利です。固定サイズに解決されなくなるため、入力ボックスが小さすぎる場合に、プロンプトの前半で入力した内容を確認するためにスクロールする必要がなくなります。

対応ブラウザ

  • Chrome: 123。
  • Edge: 123。
  • Firefox: サポートされていません。
  • Safari: サポートされていません。

ソース

デモのスクリーンキャスト

ライブデモ

textarea, select, input {
  field-sizing: content;
}

フィールドのサイズ設定の詳細を確認する。

<hr><select>

セレクタで <hr> または水平線要素を有効にできる機能も、小さいながらも便利なコンポーネント機能です。セマンティックな用途はあまりありませんが、選択リスト内のコンテンツを適切に分割するのに役立ちます。特に、プレースホルダ値など、optgroup でグループ化する必要がないコンテンツを分割するのに役立ちます。

スクリーンショットを選択

Chrome でライトモードとダークモードを選択したときの時間のスクリーンショット

[ライブデモ] を選択

<select name="majors" id="major-select">
  <option value="">Select a major</option>
  <hr>
  <optgroup label="School of Fine Arts">
    <option value="arthist">
Art History
  </option>
  <option value="finearts">
    Fine Arts
  </option>
...
</select>

詳しくは、select で hr を使用するをご覧ください。

利便性の向上

私たちは常にイテレーションを続けており、それはインタラクションとコンポーネントだけの問題ではありません。この 1 年間で、他にも多くの QOL アップデートがリリースされています。

先読みによるネスト

ネイティブ CSS のネスト機能は昨年すべてのブラウザでリリースされましたが、その後、先読みをサポートするように改善されました。つまり、要素名の前に & を付ける必要がなくなりました。これにより、ネストがより人間工学に基づいたものになり、以前に慣れていたものに似たものになりました。

対応ブラウザ

  • Chrome: 120。
  • エッジ: 120。
  • Firefox: 117.
  • Safari: 17.2。

ソース

CSS のネストで私が気に入っているのは、コンポーネントを視覚的にブロックできることです。それらのコンポーネントには、コンテナクエリやメディアクエリなどの状態や修飾子が含まれます。以前は、特定の目的のために、これらのクエリをすべてファイルの下部にグループ化していました。コードの残りの部分のすぐ近くに、わかりやすい方法で書き込むことができます。

.card {
  /* card base styles */

  h2 {
    /* child element style */
  }

  &.highlight {
    /* modifier style */
  }

  &:hover, &:focus {
    /* state styles */
  }

  @container (width >= 300px) {
    /* container query styles */
  }
}

ブロック レイアウトのコンテンツの配置

ブロック レイアウトで align-content などの中央揃えメカニズムを使用できるようになったのも、非常に便利な変更です。つまり、flex レイアウトやグリッド レイアウトを適用しなくても、div 内で垂直方向に中央揃えを行うことができます。また、これらのレイアウト アルゴリズムでは望ましくない、余白の圧縮を防ぐなどの副作用も発生しません。

対応ブラウザ

  • Chrome: 123。
  • Edge: 123。
  • Firefox: 125.
  • Safari: 17.4。

スクリーンショット

ライブデモ

div {
  align-content: center;
}

テキストの折り返し: バランスと美しさ

レイアウトについて言えば、text-wrap: balancepretty の追加により、テキスト レイアウトが大幅に改善されました。text-wrap: balance はテキストのブロックをより均一にするために使用され、text-wrap: pretty はテキストの最後の行のシングルトンを減らすことに重点を置いています。

デモのスクリーンキャスト

ライブデモ

次のデモでは、スライダーをドラッグして、見出しと段落に対する balancepretty の効果を比較できます。デモを別の言語に翻訳してみてください。
h1 {
  text-wrap: balance;
}

詳しくは、text-wrap: balance をご覧ください。

国際的なタイポグラフィの更新

CJK テキスト特徴のタイポグラフィ レイアウトの更新では、自然なフレーズ境界で行をラップする word-break: auto-phrase 機能など、過去 1 年間に多くの素晴らしい更新が行われました。

対応ブラウザ

  • Chrome: 119.
  • Edge: 119.
  • Firefox: サポートされていません。
  • Safari: サポートされていません。

word-break: 自然なフレーズ境界で行を折り返します。
word-break: normalword-break: auto-phrase の比較

text-spacing-trim: 句読点の間にケーニングを適用して、中国語、日本語、韓国語のタイポグラフィの可読性を高め、視覚的に優れた結果を得ることができます。

対応ブラウザ

  • Chrome: 123。
  • Edge: 123。
  • Firefox: サポートされていません。
  • Safari: サポートされていません。

ソース

text-spacing-trim を使用すると、CJK ピリオドの右半分が削除されます。
句読点が連続して表示される場合は、CJK のピリオドの右半分を削除する必要があります。

相対色の構文

色テーマ設定では、相対色構文が大幅に更新されました。

この例では、色に Oklch ベースのテーマ設定を使用しています。スライダーに基づいて色相の値を調整すると、テーマ全体が変更されます。これは相対色の構文で実現できます。背景は、色相に基づいてプライマリ カラーを使用し、明度、彩度、色相の各チャネルを調整して値を調整します。--i は、値のグラデーションのリスト内の兄弟インデックスです。これは、ステップとカスタム プロパティ、相対色構文を組み合わせてテーマを作成する方法を示しています。

デモのスクリーンキャスト

ライブデモ

次のデモでは、スライダーをドラッグして、見出しと段落に対する balancepretty の効果を比較できます。デモを別の言語に翻訳してみてください。
:root {
  --hue: 230;
  --primary: oklch(70% .2 var(--hue));
}

li {
  --_bg: oklch(from var(--primary)
    calc(l - (var(--i) * .05))
    calc(c - (var(--i) * .01))
    calc(h - (var(--i) + 5)));
}

light-dark() 関数

light-dark() 関数の導入に伴い、テーマ設定がより動的になり、簡素化されました。

対応ブラウザ

  • Chrome: 123。
  • Edge: 123。
  • Firefox: 120。
  • Safari: 17.5。

ソース

light-dark() 関数は、Adam Argyle によるこのビジュアル ダイアグラムで示されているように、色のテーマ設定オプションを簡素化して、テーマスタイルをより簡潔に記述できるようにする、人間工学的な改善です。以前は、テーマ オプションを設定するには、2 つの異なるコードブロック(デフォルト テーマとユーザー設定クエリ)が必要でした。これで、light-dark() 関数を使用して、明るいテーマと暗いテーマの両方のスタイル オプションを CSS の同じ行に記述できるようになりました。

light-dark() の可視化。詳しくは、デモをご覧ください。
html {
  color-scheme: light dark;
}

button {
    background-color: light-dark(lightblue, darkblue);
}

ユーザーがライトモードを選択した場合、ボタンの背景は明るい青色になります。ユーザーがダークモードを選択した場合、ボタンの背景は濃い青色になります。

:has()セレクタ

昨年 12 月にリリースされた :has() セレクタは、過去 1 年で最も影響力のある相互運用性のハイライトを取り上げず、最新の UI についてお話しするのはとても残念です。この API は、論理スタイルを記述するための画期的な手段です。

対応ブラウザ

  • Chrome: 105。
  • Edge: 105。
  • Firefox: 121。
  • Safari: 15.4。

ソース

:has() セレクタを使用すると、子要素に特定の子要素が含まれているかどうか、またはそれらの子要素が特定の状態にあるかどうかを確認できます。また、基本的には親セレクタとしても機能します。

Tokopedia の比較ブロックのスタイル設定に has() が使用されているデモ。

:has() は、PolicyBazaar など、多くの企業で特に有用であることがすでに実証されています。これらの企業では、:has() を使用して、比較セクションなど、内部コンテンツに基づいてブロックのスタイルを設定しています。ブロックに比較するプランがある場合や、ブロックが空の場合、スタイルが調整されます。

「:has() セレクタにより、ユーザーの選択に対する JavaScript ベースの検証を排除し、以前と同じエクスペリエンスでシームレスに動作する CSS ソリューションに置き換えることができました。–Aman Soni、Tech Lead、PolicyBazaar」

コンテナクエリ

ウェブに新たに追加され、使用が拡大している重要な機能として、コンテナクエリがあります。これにより、要素の親の固有サイズをクエリしてスタイルを適用できるようになります。ビューポート サイズのみをクエリするメディアクエリよりも、はるかにきめ細かい調整が可能です。

対応ブラウザ

  • Chrome: 105。
  • Edge: 105。
  • Firefox: 110。
  • Safari: 16。

ソース

Angular は最近、angular.dev で見栄えの良い新しいドキュメント サイトを angular.dev に立ち上げました。コンテナクエリを使用して、ページ上の利用可能なスペースに基づいてヘッダー ブロックのスタイルを設定しています。そのため、レイアウトが変更されて、複数列のサイドバー レイアウトから 1 列のレイアウトに変更された場合でも、ヘッダー ブロックは自動的に調整されます。

ヘッダーカードにコンテナ クエリを表示する
Angular.dev サイト。

コンテナクエリがなければ、このようなことを実現するのは非常に困難で、パフォーマンスに悪影響を及ぼし、サイズ変更オブザーバーと要素オブザーバーが必要でした。親のサイズに基づいて要素のスタイルを設定するのは簡単です。

スクリーンキャストのデモ

ライブデモ

Angular ヘッダーカード コンテナのクエリを再作成。

@property

そしてついに、ベースラインに @property が追加される予定です。これは CSS カスタム プロパティ(CSS 変数)にセマンティックな意味をもたらす重要な機能であり、新しいインタラクション機能を数多く実現します。@property を使用すると、CSS でコンテキスト依存の意味、型チェック、デフォルト値、フォールバック値を有効にすることもできます。これにより、範囲スタイルのクエリなど、より堅牢な機能が実現できます。これはこれまで不可能だった機能であり、CSS 言語に大きな深みをもたらします。

対応ブラウザ

  • Chrome: 85。
  • Edge: 85.
  • Firefox: 128.
  • Safari: 16.4。

ソース

デモのスクリーンキャスト

ライブデモ

@property --card-bg {
  syntax: "<color>";
  inherits: false;
  initial-value: #c0bae8;
}

まとめ

これらの強力な新しい UI 機能がすべてのブラウザで利用可能になり、可能性は無限に広がります。スクロール ドリブンのアニメーションとビュー遷移による新しいインタラクティブ エクスペリエンスにより、これまでにないほどスムーズでインタラクティブなウェブを実現できます。次世代の UI コンポーネントにより、ネイティブ エクスペリエンス全体を破棄することなく、堅牢で美しくカスタマイズされたコンポーネントをこれまで以上に簡単に構築できます。最後に、アーキテクチャ、レイアウト、タイポグラフィ、レスポンシブ デザインの品質を向上させることで、小さな問題を解決するだけでなく、さまざまなデバイス、フォーム ファクタ、ユーザーのニーズに対応する複雑なインターフェースを構築するために必要なツールをデベロッパーに提供できます。

これらの新機能により、スクロール ナレーションやアンカー ポジショニングによる要素同士の結合など、パフォーマンスに負荷のかかる機能のサードパーティ スクリプトを削除し、スムーズなページ遷移を構築し、プルダウンのスタイルを設定し、コードの全体的な構造をネイティブに改善できるようになります。

今こそ、ウェブ デベロッパーにとって絶好のタイミングです。CSS3 の発表以来、それほど大きな盛り上がりはありませんでした。これまで必要としながらも、実現を夢見ていた機能が、ついに現実となり、プラットフォームの一部になりました。そして、これらの機能を優先し、最終的に実現できるのは、皆様の声のおかげです。Google は、手間のかかる面倒な作業をネイティブで簡単に行えるようにし、ブランドの差別化につながるコア機能やデザインの詳細など、重要なものの構築により多くの時間を割けるようにする取り組みを進めています。

これらの新機能の詳細については、developer.chrome.com と web.dev で最新情報をご確認ください。これらのサイトでは、ウェブ技術に関する最新情報を Google チームが共有しています。スクロールドリブン アニメーション、ビュー遷移、アンカーの位置指定、さらにはスタイル設定可能な選択をお試しいただき、ご意見、ご感想をお寄せください。ご意見をお聞かせください。