Closed josepharhar closed 1 week ago
The fact that you can do select { ... }
to style the in-page control is pretty well established and backwards-compatible.
Maybe a stupid question, but why introduce a new ::select-button
pseudo-element that would only work in newer user agents?
https://open-ui.org/components/customizableselect/#customizing-basic-styles
The explainer has:
<select>
<option>one</option>
<option>two</option>
</select>
<style>
select, select::select-fallback-button {
font-family: monospace;
font-size: 12px;
}
</style>
I think that is a really unfortunate developer experience to have to specify both selectors. I really think this "fallback button" should only visible to the user agent. I don't think engineering wise it's an insurmountable challenge and it preserves backwards compatibility, which is nice.
Maybe consider making the fallback button full size, but "invisible" (deferring all of its styling to the parent select):
#fallback-button {
/* reset some button styles to make button "invisible" (potentially `all: unset` could work here too) */
background: unset;
border: unset;
color: unset; /* essentially the same as inherit / currentColor in this context */
/* make it take the full size of the in-page box */
width: 100%;
height: 100%;
}
Then the appearance: base
UA stylesheet would put its base styles (arrow icon, border, padding, etc.) on select:-internal-uses-fallback-button
or select:not(:has(> button))
.
It's also worth noting that:
select, select::select-fallback-button {
font-family: monospace;
font-size: 12px;
}
doesn't actually work in older browsers, because the whole declaration will be dropped as a result of not being able to parse select, select::select-fallback-button
. So you'd end up having to do:
@supports selector(::select-fallback-button) {
// duplicate styling
}
@supports not selector(::select-fallback-button) {
// duplicate styling
}
I think it would be really good to try to make styling on select
just work directly in the fallback button case at least.
Thanks for the feedback!
I like the idea of setting a bunch of properties to unset
to make them inherit from the shadow host <select>
, that would make the ::select-fallback-button
usage as shown in the explainer unneeded.
Maybe consider making the fallback button full size, but "invisible" (deferring all of its styling to the parent select):
The way I've been designing this so far is to try to make the <select>
's box "invisible" rather than the fallback or author buttons invisible, mostly by removing borders from the <select>
in appearance:base mode. This has been nice because its consistent between the cases of author provided or fallback buttons.
If we make the fallback button "invisible", then when the author provides their own button should we make that one "invisible" too? Or should we make the author apply more styles to make the <select>
's box "invisible"? For example, we could end up with the situation where by default both the <select>
has a border and the author provided <button>
has a border. I don't think this would ever be desirable, and ideally we wouldn't put the burden on the author to pick one of the borders and remove the other.
I'm also worried about the focus ring being rendered around the invisible fallback button inside the visible select, which would for example make the focus ring get rendered inside of the border and look wrong. I suppose that's something I could try adding a bunch of special casing for in the rendering of focus rings but I'd prefer not to try that.
Is there a way we could make the non-inherited properties that would affect the box of the <select>
to all be delegated to the fallback <button>
instead, like borders?
If we make the fallback button "invisible", then when the author provides their own button should we make that one "invisible" too? Or should we make the author apply more styles to make the
You could put the select box appearance: base
styles apply to select:not(:has(> button))
(or some internal pseudo-class which would represent when the fallback is used), then you wouldn't have conflicting styles if the developer wants to use their own button. If the developer specifies their own button, we can safely assume they want full control over the button, rather than trying to aim for backwards compatibility (which would likely be impossible in this case).
I'm also worried about the focus ring being rendered around the invisible fallback button inside the visible select, which would for example make the focus ring get rendered inside of the border and look wrong. I suppose that's something I could try adding a bunch of special casing for in the rendering of focus rings but I'd prefer not to try that.
If the fallback button has the full size of the select in-page box, it's likely not super noticeable. Though I think you'd want to defer focus to the parent select in this case, since authors who've previously defined styles for select:focus-visible
would likely want them to keep working.
Is there a way we could make the non-inherited properties that would affect the box of the
<select>
to all be delegated to the fallback<button>
instead, like borders?
select {
display: contents !important;
}
#fallback-button {
all: inherit;
display: inline-block;
}
is what I can think of, but it wouldn't pass over the display
value from the select.
I'm starting to think that it might be better to remove the fallback UA <button>
element entirely and replace it with a text node or a div containing text, which is more like how appearance:auto works.
We would then have to do some other fixes though:
<select>
itself have popover invoking behavior for the <datalist>
, but only if there is not an author-provided <button>
.<button>
.<button>
present?With this in mind, I like your display:contents idea more. Thanks for the suggestion! I'll try implementing it and see what happens.
This is more of implementation question at this point, but I think you're better off with a div/span or a text node than my display: contents
idea honestly. It does potentially pose some challenges, but it's more accurately represents what you're trying to achieve.
select {
display: contents !important;
}
#fallback-button {
all: inherit;
display: inline-block;
}
This seems a bit weird, why not just
fallback-button, select > button {
display: contents;
}
?
select { display: contents !important; } #fallback-button { all: inherit; display: inline-block; }
This seems a bit weird, why not just
fallback-button, select > button { display: contents; }
?
I tried prototyping this and there were no focus rings, so I'd have to additionally try making changes to how focus rings get rendered. I imagine there would also be other issues since this puts display:contents on the element which is actually getting focused.
This is more of implementation question at this point, but I think you're better off with a div/span or a text node than my display: contents idea honestly. It does potentially pose some challenges, but it's more accurately represents what you're trying to achieve.
I'll try prototyping this next to see what it looks like
This is more of implementation question at this point, but I think you're better off with a div/span or a text node than my display: contents idea honestly. It does potentially pose some challenges, but it's more accurately represents what you're trying to achieve.
I'll try prototyping this next to see what it looks like
I started prototyping this and it looks appealing so far, but I need to finish it to make sure there aren't any gaps.
I'm still working on the prototype, but so far it seems promising. I filed an openui issue to get feedback from them on this later today: https://github.com/openui/open-ui/issues/1086
Proposed resolution: Don't create a pseudo-element for select's UA "fallback" button
The CSS Working Group just discussed [css-ui] Pseudo-element for select's UA button
, and agreed to the following:
RESOLVED: do not add a pseudo-element for the user-agent fallback select button
I proposed a bunch of pseudo-elements in this issue, and I'd like to split each pseudo into a separate issue: https://github.com/w3c/csswg-drafts/issues/10462
The pseudo-element would target the
<button>
element in the UA shadowroot as described in the original issue as well as the draft HTML spec: https://github.com/whatwg/html/pull/10548Here are some options for a name:
::select-button
::select-fallback-button