公開日: 2025 年 8 月 14 日
Google I/O イベント シーズンが終了したため、今年のイベントで共有された CSS とウェブ UI の主なハイライトをまとめました。
かつて開発者が夢見ていた強力な機能がブラウザに搭載され、これまで以上に速いペースでブラウザ間の互換性が実現されています。しかし、このような進歩にもかかわらず、最も一般的な UI パターンの一部は、正しく実装することが驚くほど難しいままです。コンポーネントを構築する際に、JavaScript フレームワーク、複雑な CSS のトリック、大量のカスタムコードに頼らざるを得ないことがよくあります。
Chrome チームは、他のブラウザ ベンダー、CSSWG や WHATWG などの標準化団体、Open UI などのコミュニティ グループと協力して、これらの基本的な UI パターンを本当に簡単に実装できるようにすることに注力しています。
カスタマイズ可能な選択メニュー
<select>
要素はフォームに不可欠ですが、その内部構造はこれまでブラウザによって保護されており、一貫性のある包括的な CSS スタイリングはほぼ不可能でした。より優れた <select>
を構築するには、その構成要素である Popover API と CSS アンカー ポジショニング API を理解する必要があります。
Popover API: ベースラインに
カスタム プルダウンには、他のすべての UI 要素の上に表示され、簡単に閉じることができ、フォーカスを正しく管理するオプションのフローティング ボックスが必要です。Popover API はこのすべてを処理します。今年から Baseline Newly available ステータスに達し、すべての主要ブラウザで安定しています。
ポップオーバーを作成するには、トリガー要素(<button>
など)とポップオーバー要素自体の 2 つの部分が必要です。ポップオーバーに id
属性と [popover]
属性を指定し、ボタンの [popovertarget]
属性でその id
を参照することで、それらを接続します。
Popover API は要素のライフサイクル全体を管理し、次の機能を提供します。
- トップレイヤ レンダリング: z-index の競合がなくなりました。
- オプションのライト ディスミス機能: ユーザーがポップオーバー領域の外側をクリックすると閉じます。
- 自動フォーカス管理: ブラウザが、ポップオーバーへのタブ移動とポップオーバーからのタブ移動を処理します。
- アクセス可能なバインディング: 基盤となるインタラクション モデルがネイティブに処理されます。
<dialog>
要素がアップグレードされます
ポップオーバーは強力ですが、常に適切な選択肢であるとは限りません。たとえば、ユーザーのフィードバックが必要なページブロッキング インタラクションでは、モーダル <dialog>
の方が適切です。
これまで <dialog>
には [popover]
の便利な機能の一部がありませんでしたが、変更されています。新しい closedby="any"
属性により、モーダル ダイアログでライト ディスミス機能がサポートされるようになりました。ユーザーがダイアログの外側をクリックするか、Escape キーを押すと、ダイアログが閉じます。
また、コマンド呼び出し([command]
と [commandfor]
)は、command="show-modal"
でダイアログを開くなど、ボタンをアクションに接続する宣言型の JavaScript を使用しない方法を提供します。
<dialog> 要素 + closedby=any + コマンド呼び出し |
[popover] 属性 |
|
---|---|---|
主な用途 | モーダル インタラクション(ユーザー契約、チュートリアルなど) | 一時的な UI(メニュー、ツールチップ、カード、トースト アラート) |
Light Dismiss-able | ○ | ○ |
Traps Focus | ○ | いいえ |
Inerts ページ | ○ | いいえ |
宣言型アクティベーション | ○ | ○ |
実装 | 要素 | 属性 |
トップレイヤでレンダリング | ○ | ○ |
完全にスタイル設定可能 | ○ | ○ |
CSS アンカー ポジショニング
ポップオーバーが表示されたら、ポップオーバーを開いた要素に対して相対的に配置する必要があります。JavaScript で手動で計算すると、脆弱性が生じ、パフォーマンスが低下する可能性があります。
Chrome 125 以降では、CSS アンカー ポジショニング API を使用できます。この新機能では、ある要素を別の要素に宣言的に関連付け、画面の端に近づいたときに自動的に再配置を処理します。この機能は、要望の多い機能を実装するためのクロスブラウザ イニシアチブである Interop 2025 の一部です。つまり、2025 年末までにすべての主要ブラウザに実装されることが期待されます。

anchor-name
プロパティと position-anchor
プロパティを使用して要素を明示的にリンクできますが、仕様と Chrome 133 の更新により、<popover>
とその呼び出し元の <button>
の間に暗黙的なアンカー関係が作成されます。これにより、コードが大幅に簡素化され、position-area: bottom span-left
などの 1 行の CSS でポップオーバーを配置できるようになります。
chrome.dev のアンカー ツールは、position-area
を使用して目的の配置を取得する方法を示しています。
さらに、position-try-fallbacks
でフォールバックを定義することで、アンカーが画面外に出ないようにブラウザでアンカーの位置を調整できます。次のデモは、このプロパティを組み込みの再配置ロジックに使用するポップオーバーを示しています。
真にカスタマイズ可能な <select>
以前のバージョンでこれらのビルディング ブロックが配置されたため、<select>
要素のウェブネイティブ スタイリングが Chrome 134 でついに実現しました。これには、新しい appearance
プロパティ、新しい疑似要素、<selectedcontent>
要素が含まれます。
カスタマイズを有効にするには、appearance: base-select;
を <select>
要素とその新しい ::picker(select)
疑似要素に適用します。この疑似要素は、オプションのプルダウン リストをターゲットにします。これにより、次のスタイリング用の新しい内部パーツが公開されます。
<selectedcontent>
: ボタンに表示される選択したオプションのコンテンツを表します。::picker-icon
: プルダウン矢印アイコン<option>:checked
と::checkmark
: 選択したオプションとそのチェックマーク インジケーターのスタイル設定

これにより、オプション内にリッチ コンテンツを含めたり、表示を細かく制御したりできます。たとえば、オプション リストではアイコンとサブタイトルを表示し、閉じた状態では selectedcontent
内の display: none
を使用して非表示にできます。
この API は段階的に拡張できます。これらの機能をサポートしていないブラウザでは、ユーザーは引き続き機能的なウェブネイティブの選択機能を利用できます。ウェブネイティブの select 要素の組み込みのユーザー補助機能、キーボード ナビゲーション、フォーム統合を維持しながら、カスタムルックを実現できます。
カルーセル
カルーセルは、ウェブのあらゆる場所で使用されており、ヒーロー セクションだけではありません。これには、アプリストアの UI のようなタイトなレイアウトで水平方向にスクロール可能なコンテンツが含まれます。しかし、ウェブでカルーセルを構築するのは依然として困難であり、状態管理、スクロール ジャンプ、インタラクティビティ、アクセシビリティなど、考慮すべき点が数多くあります。しかし、よく考えてみると、カルーセルは基本的に、UI のアフォーダンスが追加されたおしゃれなスクロール領域です。
スクローラーのスタートガイド
カルーセルを作成するには、コンテナからオーバーフローするアイテムのリストから始めます。コンテンツをスクロール可能にしたまま水平スクロールバーを非表示にするには、scrollbar-width: none
を使用します。また、スクロールを「スナップ」させるために、scroll-snap-type
と scroll-snap-align
を適用します。これにより、ユーザーがスクロールするとアイテムが所定の位置にスナップされます。
::scroll-button
を使用した前後の移動
Chrome 135 で導入された新しい ::scroll-button()
疑似要素は、ステートフルでアクセス可能な「次へ」ボタンと「前へ」ボタンを生成するようブラウザに指示します。ブラウザは、正しい ARIA ロールとタブ順を自動的に処理し、先頭または末尾に達したときにボタンを無効にすることさえできます。これらはすべて、JavaScript を追加することなく行われます。
スクロール ボタンを開始するには、次のようにコンテンツとアクセシビリティ ラベルを指定します。
.carousel {
&::scroll-button(left) {
content: "⬅" / "Scroll Previous";
}
&::scroll-button(right) {
content: "⮕" / "Scroll Next";
}
}

これらのボタンのスタイルを設定し、CSS アンカー ポジショニングを使用して親カルーセルに対する相対位置を設定します。これは、推奨されるアプローチです。
::scroll-marker
を使用したダイレクト ナビゲーション
ドット インジケーターまたはサムネイルの場合、::scroll-marker
疑似要素と ::scroll-marker-group
疑似要素は、ナビゲーション マーカーをスクロール コンテナ内のアイテムに直接関連付けます。ブラウザはグループを tablist
として扱い、キーボード ナビゲーションを処理します。
スクロール ボタンと同様に、content
プロパティでオプトインしてスクロール マーカーを開始し、アクセシビリティ ラベルを指定します。次の例では、データ属性を使用してスクロール マーカーのラベルを設定しています。また、scroll-marker-group
プロパティを使用して、::scroll-marker-group
内のスクロール マーカーを配置します。最後に、新しい :target-current
疑似クラスを使用してアクティブなマーカーのスタイルを設定します。基本的なカルーセルの場合、次のようなコードになります。
.carousel {
scroll-marker-group: after;
> li::scroll-marker {
content: ''/ attr(data-name);
}
> li::scroll-marker:target-current {
background: blue;
}
}

スクロール状態のクエリ
スクロール関連の新しい CSS 機能を使用すると、より動的でインタラクティブなカルーセルを作成できます。スクロール状態クエリは、スクローラーの状態に基づいて適用される新しいメディアクエリです。スクロール状態クエリには 3 種類あり、@container
ステートメントで scroll-state()
を使用してアクセスできます。それらは次のとおりです。
scroll-state(snapped)
: 要素が「スナップ」位置にある場合に一致します。カルーセルでは、カルーセルの中心にスナップされたときです。scroll-state(stuck)
: 親がスティッキーになったときに、ヘッダーなどの要素のスタイルを設定します。scroll-state(scrollable)
: フェードなどの視覚的なインジケーターを追加して、スクロールできるコンテンツがまだあることを示します。
まとめ
新しい CSS カルーセル プリミティブ、スクロール状態クエリ、アンカー ポジショニングを組み合わせることで、カスタマイズされたインタラクティブなカルーセルを簡単に構築できます。スクロール駆動型アニメーションを組み込んで、アニメーションをスクロール位置に直接リンクさせ、スクロールしてビューに表示されるアイテムが拡大縮小したりフェードインしたりするようなパフォーマンスの高い効果を作成することもできます。これらのアニメーションはメインスレッドから実行されるため、スムーズな操作性を実現できます。
このインタラクティブなカルーセルでは、scroll-state()
クエリ、::scroll-button
、::scroll-marker
、CSS アンカー ポジショニング、:target-current
を組み合わせています。
また、interactivity
という新しいプロパティを使用して、ユーザーがアクティブなコンテンツに集中できるようにすることもできます。interactivity: inert
を使用すると、CSS を使用して非活性を適用し、画面外のカルーセル アイテムをフォーカス不可にして、アクセシビリティ ツリーから削除できます。
詳しくは、CSS カルーセルをご覧ください。
インタラクティブなホバーカード
ユーザー名やリンクにマウスオーバーしたときに表示されるリッチなポップアップであるホバーカードは非常に便利ですが、正しく構築するのが難しいことで知られています。遅延、イベント処理、マルチデバイス サポートを適切に実装するには、専任チームが数か月を要する場合があります。しかし、この問題を完全に解決する新しい宣言型ソリューションに取り組んでいます。
[interestfor]
のインタレスト トリガー ポップオーバー
宣言型ホバーカードの背後にある主なマジックは、[interestfor]
属性です。この新機能は、ポップオーバーの機能を活用しつつ、ユーザーの「興味」に基づいてポップオーバーをトリガーします。たとえば、ポインティング デバイスでのユーザーの関心は、ポインターのホバー、キーボードでのタブ ナビゲーション、タッチスクリーンでの長押しまたはタップなどです。モバイルでのやり取りはまだ解決されていません。
クリックベースのポップオーバーをインタレスト ベースのポップオーバーに変換するには、呼び出し要素(<button>
または <a>
)を構築し、[popover]
要素の id
と等しい [interestfor]
属性を付与します。HTML では次のようになります。
<button interestfor="profile-callout">
...
</button>
<div id="profile-callout" popover>
...
</div>
ブラウザは、次のような複雑なイベント ロジックをすべて処理します。
- 入力イベントと終了イベント: ファイン ポインタ デバイスでのホバー入力、キーボードでのタブ ナビゲーション、コース ポインタ デバイスでの長押しまたはタッチ。
- イベントの遅延: 1 つの CSS プロパティでエントリと終了の遅延を制御します。
この機能は、トップレイヤのサポートなど、他のポップオーバー機能もサポートしています。ポップオーバーは、DOM ツリーの残りの部分の上の新しいレイヤにレンダリングされます。セマンティック コンポーネント バインディングと基盤となるユーザー補助ツリーモデルはネイティブに処理されます。
インタレスト起動元のスタイルを設定する
インタレスト呼び出し元には、いくつかの新機能が含まれています。その 1 つが、CSS プロパティ interest-target-delay
を使用してエントリと終了の遅延を制御できることです。もう 1 つは、:has-interest
疑似クラスを使用して、呼び出し要素にインタレストがあるかどうかに基づいてスタイルを設定できることです。
[interesttarget] {
interest-target-delay: 0s 1s;
&:has-interest {
background: yellow;
}
}
popover="hint"
と多機能 UI
インタレスト インボーカーの重要な要素は、新しいポップオーバー タイプ popover="hint"
です。他のポップオーバーとの主な違いは、ヒント ポップオーバーが開いても他のポップオーバーが閉じないことです。これは、すでに開いているメニューやチャット ウィンドウを閉じずに表示する必要があるツールチップやプレビュー カードに最適です。
Browser Support
popover=auto | popover=manual | popover=hint | |
---|---|---|---|
ライトの閉じる(クリックアウェイまたは esc キー) | ○ | × | ○ |
開くと他の popover=auto 要素を閉じます | ○ | いいえ | いいえ |
開くと他の popover=hint 要素を閉じます | ○ | × | ○ |
開くと他の popover=manual 要素を閉じます | いいえ | × | いいえ |
JS(showPopover() または hidePopover() )でポップオーバーを開閉できる | ○ | ○ | ○ |
次のタブストップのデフォルトのフォーカス管理 | ○ | ○ | ○ |
popovertargetaction で非表示にしたり、切り替えたりできます | ○ | ○ | ○ |
親 popover 内で開いて親を開いたままにできる | ○ | ○ | ○ |
これにより、強力な多機能 UI を宣言的に構築できます。1 つのボタンで、プライマリ クリック アクション(通知パネルを開くなど)に popovertarget
を使用した自動ポップオーバーと、ポインタを合わせたときに役立つツールチップを表示するインタレスト呼び出しヒント ポップオーバーを同時に使用できるようになりました。
未来は宣言型
ここで取り上げる機能は、より強力で宣言型のウェブ プラットフォームへの根本的な変化を表しています。状態管理とアクセシビリティという複雑で反復的な作業をブラウザに任せることで、大量の JavaScript を削除し、パフォーマンスを向上させ、革新的で魅力的なユーザー エクスペリエンスの作成という得意分野に集中できます。ウェブ UI はまさに黄金時代を迎えており、その始まりにすぎません。より強力なウェブを簡単に構築できるようになるまでの過程を、こちらでご紹介します。
その他のリソース: