🎄Open UI Advent Calendar: Day 11 / Customizable Select Element Ep.9

Published on December 11, 2024

Customizable Select Elementの関連仕様: `appearance: base-select;` - `::picker-icon`のデフォルトスタイルはどうやって決まったのか

Table of Contents

Table of Contents

はじめに

Customizable Select Element Ep.9から、 appearance: base-select;で提供される、CSE のデフォルトの見た目が決定された背景の議論をお話ししています。

Ep.9 では、<option>::checkmarkが現状の見た目となった背景について深掘りました。 今回は、::picker-icon部分について取り上げます。

2024/12/9時点でのselectの各パーツの定義 2024/12/9時点でのselectの各パーツの定義

Customizable Select Elementの関連仕様

ボタン要素右の矢印アイコン

CSE のデフォルトのスタイルでは、ポップオーバー部分をトリガーする<button>の右に「▼」矢印アイコンが表示されます。

初期段階では、この矢印アイコンはselect::afterとして実装されていましたが、後に::select-arrowとなり、現在では::picker-iconとなっています。

デフォルトスタイルを決めるIssueの初期段階では、select::afterという既存の擬似要素をそのまま使用して提案されていました。(現在はこの Issue の親コメントの内容は最新のものに変わっている)

もともと::before::afterで実装されていたのは、::before::afterが「diplay: none;などで簡単に上書きできる」という要件を満たしつつ、UA スタイルシートでの実装も容易だったためです。

しかし、デフォルトの擬似要素に加えて、::before``::afterを要素に当てたいというユースケースも考えられます。 例えば、<li>のデフォルトの行頭文字は Bullet で::markerとしてレンダーされますが、<li>::markerだけでなく::beforeでも「何か別の要素(🎄)」を配置したい場合、次のように記述できます。

li::marker {
  font-size: 1.5rem;
  color: orange;
}
li::before {
  content: '\1F384';
  margin-right: 10px;
}

::markerを上書きする ::markerを上書きする

しかし、もし::markerが存在せず、UA スタイルシートにli::beforeで Bullet が実装されていた場合はどうでしょうか。<li>::beforeはもう UA によって使われているため、Bullet と「何か別の要素(🎄)」の二つを配置することは困難です。


これに関して、デフォルトでは::select-arrowなどの新しい擬似要素を提案するべきとの指摘があり、TPAC 2024 の Open UI と CSSWG の Joint Session で話し合われる運びになりました。

先ほどの::markerのようなケースのみならず、既存の::before``::afterを UA で使用するとさまざまな考慮事項が発生します。

例えば、Author スタイルシートの::afterを使ってボタン要素右の矢印アイコンを全く独自のものに置き換えるケース考えてみましょう。 次のように、UA スタイルシートがボタン要素右の矢印アイコンを::afterで実装すると、以下をやらねばならなくなります。

  1. UA スタイルシートのselect::afterに何が当たっているか DevTools を開いて確認する
  2. Author スタイルシートで次の 3 つのプロパティを上書きする
  3. 独自のアイコンにするためのスタイルを当てる
select::after {
  margin-inline-start: auto;
  display: block;
  content: counter(fake-counter-name, disclosure-open);
}

一方、UA が、::before ::afterではなく新しい擬似要素で実装すると、新しい擬似要素をdisplay: none;するだけで、デフォルトの矢印アイコンを削除でき、Author スタイルシートでの上書きが容易になります。

加えて、目的に沿った命名の擬似要素を定義することで、要素の目的を明確にできるという利点もあります。

こうした議論の結果、既存の::afterではなく、新しく擬似要素を定義するという結論に至りました。

RESOLUTION: create new pseudo elements for checkmark and dropdown icon for base appearance select instead of using ::before and ::after in the UA stylesheet ACTION: Tab and fantasai to make better words for this in the css-pseudo spec

擬似要素のカテゴリ

新しい擬似要素を実際に仕様書に記載する際、擬似要素を Tree-Abiding とするか Element-Backed にするかという話がありました。

擬似要素は 2 種類に大別でき、Tree-Abiding と Element-Backed はそれぞれ次のような特徴があります。

Tree-Abiding擬似要素 Tree-Abiding擬似要素

Element-Backed擬似要素 Element-Backed擬似要素

::selected-arrowは、元々select::afterとして定義&実装されていたように、それ自体は Box Tree の中には存在しないtree-abidingな擬似要素なので、仕様書にもtree-abidingな擬似要素とカテゴライズされることになりました。

gregwhitworth RESOLVED: add pseudo-elements for the select button and option checkmarks which are fully stylable pseudo-elements with content specified by the content property https://logs.csswg.org/irc.w3.org/css/2024-10-24/

::selected-arrow::picker-iconに決定される

::selected-arrowは暫定的な名前だったため、要素に対する議論&投票が行われ、最終的に::picker-iconに決定され、Chromium の実装に反映されました。

RESOLVED: go with ::picker-icon https://github.com/w3c/csswg-drafts/issues/10908#issuecomment-2489173316

以下は、デフォルトの::picker-iconをカスタマイズした例です。

.customized-picker-select {
  appearance: base-select;
  &::picker(select) {
    appearance: base-select;
  }
  /* デフォルトの::picker-iconは簡単に消せる */
  &::picker-icon {
    display: none;
  }
  /* ::afterを使って独自のドロップダウンボタンを実装できる */
  &::after {
    content: "";
    display: inline-block;
    width: 35px;
    height: 35px;
    background-image: url(https://blog.sakupi01.com/icon.svg);
    background-size: contain;
    vertical-align: middle;
  }
}

デモ:

See the Pen Customized Select Element - Playground by saku (@sakupi01) on CodePen.



今回はポップオーバーを開閉するボタン要素右の矢印アイコン、::picker-iconを取り上げました。

上記 Issue に記されているデフォルトスタイルになった背景について、次回からも引き続き見ていこうと思います。

それでは、また明日⛄

See you tomorrow!

Appendix