Customizable Select ElementにおけるParser RelaxationのアップデートとShipの背景

2025-01-26

目次

目次

  1. はじめに
  2. Parser Relaxation
  3. Parser RelaxationはChrome 131でShipされていた
  4. Parser Relaxation無効化の背景
  5. Parser Relaxationの有効化
  6. そのほかの懸念

はじめに

<select>のスタイルや機能拡張を行うために、これまでに多くの関連機能が提案され、仕様策定され、実装されてきました。 その中でも特に、Customizable Select Elementを実現する上で欠かせなかった、HTML Parserの緩和に関するバグが、後方互換性の心配が非常に低くなる程度に修正され、ShipのIntentが発表されました。

本エントリでは、今回のIntentに影響を与えた、Parser Relaxationについて見ていきます。

Parser Relaxation

新しい<select>では、以下のように、カスタムの<button>を設置したり、<option>の中に任意のタグを挿入したりすることができます。これによって、独自のボタンで::picker(選択肢のポップアップ)をトリガーしたり、<option>の中に<img>や任意のコンテンツを入れて、選択肢として表示することが可能になります。

<style>
select,
::picker(select) {
  appearance: base-select;
}
option::checkmark {
  display: none;
}
</style>
<select>
  <button>
    <selectedcontent></selectedcontent>
  </button>
  <option value="andorra">
    <img src="https://upload.wikimedia.org/wikipedia/commons/thumb/1/19/Flag_of_Andorra.svg/120px-Flag_of_Andorra.svg.png" alt="" />
    <span>Andorra</span>
  </option>
  ...
</select>

Country select with Flags Country select with Flags

しかし、現状の<select>では<option>, <optgroup>, <hr>のみを内部要素として許可しているため、これらの要素以外を含む<select>がうまくパースされるよう、<select>のContent Modelを変更し、それに応じてHTMLパーサに変更を加える必要があります。

Content model: Zero or more option, optgroup, hr, and script-supporting elements. https://html.spec.whatwg.org/multipage/form-elements.html#the-select-element

Parser RelaxationはChrome 131でShipされていた

このParser Relaxationは、Chrome 131でShipのIntentが出ており、実際にChrome 131でShipされていました。

この時点では、パーサの変更による既存の<select>との後方互換性が懸念されていたため、まず一度Parser RelaxationをShipしてみて、ユーザからのフィードバックを受けつつ、適切な対処がされるというモチベーションでした。

This change is in support of the customizable <select> feature but is being shipped first because it can be done separately and has some compat risk which I'd like to get feedback on. ... If there are major issues with this change, I will reassess and make adjustments to the parser as needed.

Parser Relaxation無効化の背景

Chrome 131でShip後、選択肢ドロップダウンが正常に動作しない問題が複数報告されます。

このバグは、<option><div>など任意のHTML要素の子要素となっていた場合、ドロップダウンが開かないというものでした。

Basically if options inside select element are wrapped in other HTML tag like astro-slot (Astro/SolidJS setup) or even a simple DIV, dropdown does not open. Reproducible only on Chrome 131, after this https://chromestatus.com/feature/5145948356083712

ref: https://issues.chromium.org/issues/379034733#comment10

この問題は、Parser Relaxationの変更によって発生したものであることが判明し、Chrome 131, 132でParser Relaxationを無効化することで対応されました。

I disabled this new parser behavior in chrome 131 due to a bug with one of multiple code paths which collects options to render in the select's popup which doesn't exist in the spec. ...

I think it makes sense to wait with merging this PR until it has been shipping in Stable for a bit.

That sounds reasonable to me especially since shipping this change in chrome is not blocked by merging this PR.

ref: https://github.com/whatwg/html/pull/10557#issuecomment-2515300782

Parser Relaxationの有効化

一時は無効化された機能でしたが、上記のバグは以下で修正され、これまでに、Parser Relaxationによるその他リグレッションのほとんども解消されてきました。

Chrome 133からはParser RelaxationはFinchされており、その他Customizable Select Element関連の実装もChrome 134でShipされることに繋がります。

そのほかの懸念

Relaxation以前のパーサの挙動では動作していた<select /> <input />といった書き方が、Parser Relaxationによって動作しなくなるという懸念は、現時点でも依然として残るようです。

たとえば、以下のようなHTMLで、<input>がレンダーされる/されないという挙動の違いが確認されています。

<select></select> <input />
 
<hr />
 
<select /> <input />

Experimental Web Platform features enabled

Chrome Canary 134 Chrome 131
Chrome Canary 134 Chrome 131

これに関しては、専用のフラグが用意されているため、もしロールアウトして問題があっても、Chromeのリリースを伴わずに機能を無効にすることができます。


数多くの構文と動作変更を繰り返してきたCustomizable Select ElementのShipは、Joey Arharによる、辛抱強い繰り返しの実装の末に実現されています。

Webの開発体験を大きく変えるたくさんの機能の実現にも貢献してきた、Customizable Select Element。長年実現が待ち望まれていた新しい機能のリリースなだけ、とてもワクワクさせられます🎉

Copyright © 2025 saku 🌸 All rights reserved.