The State of ${Web UI}

Burikaigi 2026
saku🌸 / @sakupi01

saku

🤗
Design Technologist / ex-Web Frontend @Cybozu

Google Developer Expert for Web Technologies 🌏✨

How Cybozu eliminated browser compatibility overhead with Baseline | web.dev


免責事項

  • 今回紹介する機能は、Web Features にもないような、まだ提案段階のものが多く、将来的に大いに変更される可能性があります。
  • とはいえ、説明の都合を優先して、現時点で利用されているものを使っています。
  • 発表時点での仕様策定状況やブラウザ対応状況は 2026年1月時点のものです。最新の情報は各 WG での動向やブラウザの実装状況をご確認ください。

Check out for Browser Status!:

The State of ${Web UI}

State of Web UI なんて壮大なテーマ、 30分で喋れるわけもなく、絞りに絞って、 「この流れを知らずに 2026年は生きられない」 という「チェックポイント」を、独断と偏見と納得感で3つだけピックアップしました。
なので、きっと皆さんが思うような「これを聞けば今年の Web UI が全部わかる」にはなっていないと思います。
期待してくれていた人に対するせめてもの埋め合わせとして、「登壇後の議論までがこのトーク」とします。
「あれについては喋らんのかい」「これの近況ってどうなってるの?」 「実務ではどう使えそうなの?」etc etc 、ぜひ後で声かけてください:)
~saku

The State of Customizable Select Element

1. Customizable Select Element 自体のパターン拡張

2. 新たな UI パターン -- Customizable Menu への貢献

3. 進化する Primitives

1. Customizable Select Element 自体のパターン拡張

2. 新たな UI パターン -- Customizable Menu への貢献

3. 進化する Primitives

Variations of Select

Variation Trigger UI Picker UI [Single / Multiple]
Dropdown Select button Dropdown Both
Listbox Select - Listbox Both
Datalist Select input[list] datalist Single Only
Filterable Listbox Select input[filter] Listbox Both
Combobox🎉 button Filterable Listbox Select
Dropdown
Both

Appearance Variations of Select

  • [Single | Multiple]
    1. Single
    2. Multiple
  • Trigger UI
    1. Button
    2. Filterable Input (input[filter])
    3. Datalist (input[list])
  • Picker UI
    1. Dropdown(Popup)
    2. Listbox(In-page)
    3. Datalist (input[list])

2025年は Select UI を主に 3つのパートで分けて仕様策定し、
それぞれのパーツを組み合わせて新しいパターンの Select の実現を図りました。

${Select UI} = ${Trigger UI} + ${Picker UI} + [Single | Multiple]

Single&Multiple Dropdown Select

Dropdown Select = Button + Dropdown + [Single | Multiple]

  • Dropdown Select(ドロップダウン式の選択)UI
    • Dropdown = ポップアップで表示される選択肢のリスト
    • Dropdown Select🎉 = Button + Dropdown + [Single | Multiple]

Do we need OK/Cancel Buttons?

1. Android 方式

  • OK と Cancel ボタン
  • 選んでも OK しないと確定しない
  • Cancel を押すと変更は全て戻る

2. iOS 方式

  • Close ボタンのみ
  • 選ぶとすぐに確定
  • Close ボタン or Light Dismiss で閉じる

3. 現状の実装

  • ボタンなし
  • 選択肢を選ぶと、すぐに確定
  • Light Dismiss か、選択元のボタンをクリックで閉じる

Should select multiple with popup have OK/Cancel buttons? · Issue #1217 · openui/open-ui

Dropdown = Popup 🤝🏻 Listbox

Dropdown = Popup ✂️ Listbox

[New Primitive!]

Customizable Listbox

Customizable Listbox の見た目

Listbox Single&Multiple Select (CSE with size >=2 & multiple)

Listbox Select = ${} + Listbox + [Single | Multiple]

  • Listbox Select(リストボックス式の選択)UI
    • Listbox = ページ内選択肢のリストそのもの
    • Listbox Select🎉 = ${} + Listbox + [Single | Multiple]

What about... 絞り込み機能付きの Select?

Datalist Combobox (Filterable CSE = input[list] + datalist)

Datalist Select = Customizable input[list] + Customizable datalist + Single Only

  • Datalist Select(Datalist を使った絞り込み)UI
    • Datalist Select🎉 = Customizable input[list] + Customizable datalist + Single Only

[New Primitive!]

Customizable filter-able Input

Filterable Select (Input-Select Assosiation Primitive = input[filter] + Listbox)

Filterable Listbox Select = input[filter] + Listbox + [Single | Multiple]

  • Filterable Listbox Select(絞り込み付き Listbox)UI
    • Listbox = ページ内選択肢のリストそのもの
    • Filterable Listbox Select🎉 = input[filter] + Listbox + [Single | Multiple] = 絞り込み付き Listbox UI パーツ

Combobox (Popup Input-Select Assosiation Primitive)

Combobox = Button + Filterable Listbox Dropdown(Popup + Filterable Listbox) + [Single | Multiple]

  • Combobox(ドロップダウン式の絞り込み付き Listbox)UI
    • Filterable Listbox = 絞り込み付き Listbox UI パーツ
    • Filterable Listbox Dropdown = Popup + Filterable Listbox = ポップアップで表示される絞り込み付き Listbox UI パーツ
    • Combobox🎉 = Button + Filterable Listbox Dropdown + [Single | Multiple]

Overview of Primitives Combination of Customizable Selects

  • Dropdown Select(ドロップダウン式の選択)UI

    • Dropdown = ポップアップで表示される選択肢のリスト
    • Dropdown Select🎉 = Button + Dropdown + [Single | Multiple]
  • Dropdown Select(ドロップダウン式の選択)UI

    • [New!]Listbox = ページ内選択肢のリストそのもの
    • Dropdown = Popup + Listbox
    • Dropdown Select🎉 = Button + Dropdown + [Single | Multiple]
  • Listbox Select(リストボックス式の選択)UI

    • Listbox = ページ内選択肢のリストそのもの
    • Listbox Select🎉 = Listbox + [Single | Multiple]
  • Datalist Select(Datalist を使った絞り込み)UI

    • Datalist Select🎉 = Customizable input[list] + Customizable datalist + Single Only
  • Filterable Listbox Select(絞り込み付き Listbox)UI

    • Listbox = ページ内選択肢のリストそのもの
    • Filterable Listbox Select🎉 = input[filter] + Listbox + [Single | Multiple]
  • Combobox(ドロップダウン式の絞り込み付き Listbox)UI

    • Filterable Listbox = 絞り込み付き Listbox UI パーツ
    • Filterable Listbox Dropdown = Popup + Filterable Listbox
    • Combobox🎉 = Button + Dropdown Filterable Listbox + [Single | Multiple]

1. Customizable Select Element 自体のパターン拡張

2. 新たな UI パターン -- Customizable Menu への貢献

3. 進化する Primitives

Roving tabindex

  • メニューや Select のようなフォーカスする要素を多く含んだ UI では、キーボードユーザはそのコンポーネントを抜るのに Tab を連打する必要がある
  • そのため、「コンポーネント間」を移動するために Tab を使えるようにし、「コンポーネント内」は矢印キー/Clickで移動する

  1. Tab で移動しないよう、フォーカス可能な全要素を tabindex="-1" にしておく
  2. 最初に選択する1つだけを 0 に設定しておく
  3. 矢印キーやクリックしたときに移動先のボタンを 0 にし、他を -1にしてリセットする
  4. 新しく 0 になった要素に .focus() を呼び出す

tabindex を付け替えて回って、移動させているので「Roving tabindex」。
Customizable Select Element ではこの仕組みが組み込まれてる。

Standardizing Roving tabindex

out of Customizable Select's Built-in Focus Management feature!

Focusgroup(Revamped)

<div focusgroup="<behavior> [inline|block] [wrap] [no-memory]">
  <button>One</button>
  <button>Two</button>
  <button>Three</button>
</div>
  • focusgroup: Roving tabindex + 最後のフォーカス要素の記憶(memory) + arrow key handling を宣言的に記述できる。属性なので、既存のマークアップに取り込める。JSでの複雑な制御がほとんど不要に
    • <behavior>: インタラクションパターンを定義する必須のトークン。指定した値に基づいて適切な role が推論される
      • toolbar, tablist, radiogroup, listbox, menu, menubar など
    • [inline | block]: 矢印キーの移動を特定の軸(横方向・縦方向)に制限する
    • wrap: 要素の端に到達した際、最初または最後の要素へループさせる設定
    • no-memory: 一度グループを離れて再度 Tab で戻った際、前回位置ではなく常に最初の要素から開始
    • Arrow Key Handling: button, input, a などのフォーカス可能要素を自動で Roving tabindex 管理対象にする

Customizable Menu

  • focusgroup がネストされると、親から分離して直近の focusgroup で新しいフォーカスループが作成される
  • サブメニュー(ネストされたグループ)を表示・非表示する際の最後のフォーカス要素の memory の取り回し。
  • menubar では inline 移動に限定し、menu では block(上下キー)移動に限定するといった、方向キーの使い分け

Impl: Menu elements tracking bug [406566432] - Chromium

1. Customizable Select Element 自体のパターン拡張

2. 新たな UI パターン -- Customizable Menu への貢献

3. 進化する Primitives

Popover API

popover & popovertarget Attributes With:

  • Top Layer
  • Default Focus Management
  • Light Dismiss
  • Built-in Keybinds
<button 
  popovertarget="hint-content" 
  popovertargetaction="toggle">

</button>
<div class="tooltip" id="hint-content" popover>
    Hi, I'm a Positioned Element
</div>

popovertarget & popovertargetaction

commandfor & command

Invoker Commands

command & commandfor Attributes

<button type="button" commandfor="my-popover" command="toggle-popover">Open Popover</button>
<div id="my-popover" popover="auto">Hello world</div>
<button type="button" commandfor="my-dialog" command="show-modal">Open Dialog</button>

<dialog id="my-dialog">
  Hello world!
  <button type="button" commandfor="my-dialog" command="close">Close</button>
</dialog>
<button type="button" commandfor="my-custom" command="--my-frobulate">Frobulate</button>
<div id="my-custom"></div>

<script>
  document.getElementById("my-custom").addEventListener("command", (e) => {
    if (e.command === "--my-frobulate") {
      alert("Successfully frobulated the div");
    }
  });
</script>

commandfor

interestfor

Interest Invokers

interestfor Attributes

  • Separation of Behavior from Structure
  • More Accessible & Declarative Hoverable UI Pattern
    • Delay Feature
    • Default Focus Management
    • Built-in Keybinds
<button class="anchor" interestfor="hint-content">

</button>
<div class="tooltip" id="hint-content" popover="hint">
    Hi, I'm a Positioned Element
</div>

what about hover on Touch Screen? Feedback Needed!

Interesttarget Contextmenu

Interesttarget Button Long Press

Customizable Select Element = Trigger + Picker

Customizable Select Element = [Button | Input[filter]] + [Popover API | Anchor Positioning | Listbox UI] + Focusgroup + [Single | Multiple]

The State of CSS Masonry

What is Masonry Layouts?

"Waterfall" Masonry

Pinterest's Waterfall Masonry

"Brick" Masonry

Brick Masonry

Anatomy of Masonry(Key Points)

  • Grid Axis: Grid のように行や列のサイズに則って、Item が配置される(Flow する)静的な軸
  • Stack Axis: 行や列の概念がなく、Item のサイズに合わせて詰めて配置される動的な軸

Anatomy of Masonry

What is NOT Masonry Layouts?

Waterfall Masonry に似ているが、Item が静的なサイズの軸(Grid Axis)で揃っていない => Not Masonry

BBC Home Page

Brick Masonry に似ているが、Item が配置される方向(Flow 方向)が静的なサイズの軸(Grid Axis)でない => Not Masonry

Google Search Result is not masonry layout

Considerations when designing with Masonry

Masonry の特徴:

  • 見た目と Tab/DOM Order が一致しない
  • 末端部分が揃わない
    • → 最もスペースが空いている箇所に Item を詰めて配置するため
  • コンテンツを stretch したり crop したりする必要がない
    • → 一方の軸(Stack Axis)が動的なのでアスペクト比を保てるため
  • 領域あたりの情報量を多くできる
    • → 「スペースを詰めるレイアウト」のため
  • etc

Grid to Masonry

... “Just Use Grid” vs “New Masonry Layout”?

Masonry を Grid に含める(Gridベース)

display: grid;
grid-template-rows: masonry;

Masonry を Grid に含めない(Masonryベース)

display: masonry;

WebKit Blog vs Chrome Blog

WebKit のブログ1
WebKit のブログ2

↔︎

WebKit のブログ1に対する Chrome のブログ
WebKit のブログ2に対する Chrome のブログ

WebKit (Grid ベース)

  • grid-template-*gap など、開発者がすでに知っている Grid プロパティをそのまま使えて良い
  • Subgrid を生かしたカスタマイズも実現できる
  • 独立させると masonry-template-tracks のような重複した新プロパティも大量に導入することになり、CSS が肥大化する

Chrome (Masonry ベース)

  • Grid は「2D(Row&Column)の配置」に対し、Masonry は「1D(軸)+詰め込み」。アルゴリズムもメンタルモデルも根本的なものが異なるので、別物として扱うべき
  • 何より、Grid にない内在サイズやその他パフォーマンス問題がある
  • display: grid を拡張する場合、Grid の初期値を引き継がなければならない。しかし、独立していれば display: masonry と書くだけで Masonry に最適化されたデフォルトを定義できる

ItemFlow という転換点

  • Flexbox の flex-flow と Grid の grid-auto-flow を統一する新しいプロパティ
    • 敷き詰め方(dense/balanced/collapsed packing)を指定する 「Item Pack
  • Masonry は、Grid の行または列を Item Flow で「collapse(崩す)するレイアウト」として定義できる
.masonry {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
  item-flow: row collapse;
  gap: 1rem;
}

Resolution for “Just Use Grid” vs “New Masonry Layout”

  • Item Flow で Masonry も統一的に説明できるようになった
  • 改めて、「Grid に直接手を加えて拡張する(Grid ベース側)か、Grid には直接手を加えたくない(Masonry 側)か」

=> 既存の Grid に統合せず、 Grid を拡張することで、Grid の資産を Masonry で利用可能にすることで合意

.masonry {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
  item-flow: row collapse;
  gap: 1rem;
}

RESOLVED: css-grid-3 に含め、 display: grid-lanes; で Masonry を有効化

  • grid-template-* など Grid の資産を活かしつつ
  • あくまでも Grid そのものではないことを主張するキーワード(よって、Grid との乖離を生まないよう、キーワードに grid を含めることが条件だった)
  • Poll の結果 grid-lanes が選ばれ、これで Flexbox でも Grid でもない新しいレイアウトが誕生
  • grid-auto-flow: normal という新しいデフォルト
    • grid-template-columns が設定されていれば Waterfall、grid-template-rows が設定されていれば Brick
    • これがあるので、 Item Flow の定義が決まっていなくても、Gird-lanes は動作可能
.masonry {
  display: grid-lanes;
  grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
  gap: 1rem;
}

The State of CSS Masonry Grid-lanes

Key Issue: Item Flow の rowcolumn の解釈問題

Flex は Shape と Flow が一致するので、 Direction を決定できる
Grid は Shape がどちらにも取れるので、 Flow が Direction を決定できる

flex-flow の shape

flex-flow の flow

grid-flow の shape

grid-flow の flow

Waterfall Masonry は item-flow: rowitem-flow: column

  • Masonry レイアウトでは Shape と Flow が一致しない
  • Shape/Flow どちらで Direction を解釈したら良いか意見が割れているのが現状
    • 「Shape」を優先するなら、 grid-auto-flow: column; は Waterfall
    • 「Flow」を優先するなら、 grid-auto-flow: column; は Brick
    • Shape 案は直感的な見え方を反映でき、Flow 案は Grid との一貫性を反映できると言える
  • これが決まると、Item Flow の仕様が芋蔓式に決定できる

Shape of Layout:
Shape of Layout

Flow of Layout:
Flow of Layout

Feedback Needed! @/[css-grid-3][masonry] item-flow row vs. column in masonry layouts · Issue #12803 · w3c/csswg-drafts

The State of Platform SPA Helpers

CSS Route Matching

Declarative Partial Updates

  • URLPattern を CSS から利用可能にし、URLベースのスタイリングを実現する
    • URLPattern の仕様に基づく URL マッチングを行う CSS 関数 url-pattern()
    • 名前付き URLPattern を定義する @route
    • URL に応じた条件付きスタイルを示す @navigation
    • 要素のリンクと URLPattern のマッチをする :link-to()
    • etc
@view-transition {
  /* allow cross-document view transitions */
  navigation: auto;
}

@route --movie-details {
  /* match URLs like /en/movie/123 which is the English page
     about a movie with ID 123 */
  pattern: url-pattern("/:lang/movie/:id");
}
.movie-container:has(> .movie-title:link-to(
  --movie-details with navigation-param(id))) {

  view-transition-name: movie-container;

  > .movie-poster {
    view-transition-name: movie-poster;
  }
}

View Transitions API

View Transitions API

Navigation API

Navigation API is SHIPPING in FF🚀: Firefox Beta 147.0beta

CSS Route Matching, View Transitions, Navigation API, Signals, Template Instantiation, (JSON, CSS, HTML) Import Attributes, (Declarative?) HTML/CSS Modules…

これらは JS フレームワークとどう関係していく・・・?

The Separation of Concerns

The Separation of Concerns

In computer science, separation of concerns (SoC) is a software engineering principle that allows software engineers to deal with one aspect of a problem so that they can concentrate on each individually. Concerns can be separated in various ways. Separation of concerns in terms of time is the underlying motivation of software development lifecycle methods.
-- Separatation of concerns - Wikipedia

HTML

-> Structure

"What does it mean?"

CSS

-> Presentation

"How does it look?"

JavaScript

-> Behavior

"What does it do?"

HTML

-> Structure

"What does it mean?"

CSS

-> Presentation

"How does it look?"

JavaScript

-> Behavior

"What does it do?"

標準化は、機能を切りわけ、所在を正しい場所に戻す作業でもある

  • e.g, Routing
    • Navigation API: 遷移という「振る舞い」を制御する
    • CSS Route Matching: 「見た目の切り替え」を CSS セレクタのようなイメージで行う
  • e.g, エコシステムの声をプラットフォームに取り入れる動き
  • フレームワークごとの挙動差が減り、ブラウザのネイティブな挙動の恩恵を、最小限のコードで受けられるようになる
  • However, 生まれ続けるユースケースに際限がない限り、全てをカバーし切ることは難しい

「Platform」と「Framework」で目的としているレイヤーは異なる

✨

The Catalyst for the Next Web

✨

Kill
Less library, more future usecases.

Thank you!

Appendix