Updates to the customizable select API
Published on
A few months ago, I shared a blog post outlining the current state of the customizable select prototype and asking for developer feedback. Since then, a lot has changed! And for the better. There were a few things re-named, and significant changes to the user agent stylesheet. Now that this feature has evolved and is hopefully close to shipping, here is a list of updates since the RFC.
High-level overview of changes:
::select-fallback-button
, which refers to the button that opens the popover was removed, and thebutton
itself is nowdisplay: contents
. This means, styles for the button should be put on theselect
element instead.- The dropdown arrow icon was changed from
select::after
toselect::picker-icon
- Checkmarks that indicate the selected option were changed from
option::before
tooption::checkmark
<selectedoption>
was renamed to<selectedcontent>
- Many styles were removed from the user agent stylesheet, such as default shadows, border-radius, and font styles
- Options now are styled using flexbox instead of block layout
I’m very happy to see the changes land that changed the use of existing pseudo elements (::before
and ::after
) to use new ones for the built-in checkmarks and icons (::picker-icon
and ::checkmark
). I think this makes a lot more sense and something I had advocated for! I’m also happy to see the rename of <selectedoption>
to <selectedcontent>
, which Jake Archibald brought up as being a potential source of confusion in his podcast, Off the Main Thread. Finally, I’m happy to see a less-intrusive UA stylesheet applied to this element. I’m always a fan of the less-is-more approach when it comes to these customizable components, because after all, the entire idea is to make them your own. And the less browser-provided styles you need to undo the better 😄.
Recap of usage
Opt-in mode
To use the new customizable select, you need to “opt-in” with appearance: base-select
on both the select itself and the picker (you may know the picker as the “dropdown”).
select, ::picker(select) {
appearance: base-select;
}
Now, you can style the select however you want and have access to new elements and pseudo classes.
New elements and pseudos
With these updates, if you want to style the button directly, you style select
. You can also use the :open
pseudo class to style the select and its picker if the picker is open.
select
is the parent element. It also acts as the button you click on to open the picker::picker(select)
is a shadow DOM element that contains the optionsoption::checkmark
contains the checkmark of the selected optionselect::picker-icon
contains the arrow icon (▼) in the button that opens the pickerselectedcontent
is an element you can use inside ofselect
to mirror the inner HTML of the currently selected optionselect:open
styles the select button when the picker is openoption:checked
styles a selected option in the picker
Demos
I have updated my demo collection with the latest syntax based on the resolutions and API updates outlined above. Definitely check them out for some inspiration and to see this feature live:
Conclusion
Thank you to everyone who provided feedback and big shoutout to all the folks working on bringing this feature to life (particularly the OpenUI community group and Joey Arhar, who has been the primary engineer patiently prototyping and re-prototyping this feature through numerous syntax and behavioral changes)!
I’m so excited to see this finally landing in Chrome! It’s a huge win for the web 🥳