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

2024-12-11

[css-ui] Pseudo-elements for checkmark and dropdown icon for appearance:base `<select>` · Issue #10908 · w3c/csswg-drafts
In this issue, I proposed putting option::before in the UA stylesheet to create checkmarks and select::after to create a dropdown icon. It was suggested that we could create new pseudo-elements for...
[css-ui] Pseudo-elements for checkmark and dropdown icon for appearance:base `<select>` · Issue #10908 · w3c/csswg-drafts favicon https://github.com/w3c/csswg-drafts/issues/10908#issuecomment-2489173316
[css-ui] Pseudo-elements for checkmark and dropdown icon for appearance:base `<select>` · Issue #10908 · w3c/csswg-drafts

はじめに

🎄 この記事はOpen UI Advent Calendarの11日目の記事です。

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にAbide(従う・倣らう)要素。それ自体は要素としてBox Treeの中には存在しない。レンダーするコンテンツは、contentプロパティ内に指定する e.g. ::before, ::after, ::select-arrow::picker-icon

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;
  }
}

デモ:


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

  • appearance: base-select;の見た目は、どのようにして決まったのか
    • 選択された<option>のデフォルトチェックマーク
    • ポップオーバーを開閉するボタン要素右の矢印アイコン
    • ボタン要素や選択肢ポップオーバーの色
    • その他のスタイル

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

それでは、また明日⛄

See you tomorrow!

Appendix

Copyright © 2024 saku 🌸 All rights reserved.