Open annevk opened 5 months ago
Thanks for making an issue for this! I imagine I could replace the ::select-fallback-datalist
or ::select-datalist
pseudo-element that I've implemented and proposed with ::picker(select)
and have everything work the same.
I like how this enables incremental opt-in, but would still require us to implement/ship appearance:base for all the non-picker form controls to truly make it incremental, right?
I also like how it enables appearance:base for the button and the popup separately, but I imagine that some authors wouldn't like the additional CSS needed to go from select { appearance:base-select; }
to select { appearance:base; } select::picker(select) { appearance:base; }
.
Just catching up on the latest status on this. I want to advocate for simplicity for this feature from a user (author) perspective.
It doesn't seem like there is a benefit to developers (or a difference) between select { appearance:base; }
and select::picker(select) { appearance:base; }
. Why force developers to remember both selectors that they will need to target, degrading the developer experience?
The most likely and straightforward developer experience would be to name these selects, i.e. with a class, and access them like .account-dropdown { appearance: base; /* styles */ }
. Ideally that is all that would be needed to enter into this new behavior, and we wouldn't require an additional pseudo class. With the picker proposal, developers would need to write:
.account-dropdown {
appearance: base;
/* styles */
}
.account-dropdown::picker(select) {
appearance: base;
}
(As an aside, would styles need to be duplicated? Where would they live, on the select itself or on the ::picker
pseudo?)
Similarly, I would prefer not to have custom identifiers with specified names for each type of select. ::picker(form-control-identifier)
is a more roundabout authoring experience than just targeting your element via a class or other developer-owned identifier. This requires developers to remember the custom identifier for each type of picker in addition to the custom class name they have likely selected to target the picker. In reality, developers will likely need to be looking up these identifier values to make sure they're getting them right.
A natural developer experience would be to connect their custom code like:
.profile-color {
appearance: base;
/* rest of your styles */
}
Rather than connect it and then look up the correct picker to sync with:
.profile-border-color {
appearance: base;
/* rest of your styles */
}
.profile-border-color::picker(color) {
appearance: base;
}
Is it possible to infer the types here to prevent this additional lookup and code for a more seamless developer experience?
It doesn't seem like there is a benefit to developers (or a difference) between select { appearance:base; } and select::picker(select) { appearance:base; }. Why force developers to remember both selectors that they will need to target, degrading the developer experience?
I agree with Una that this adds extra overhead for developers. Under the premise that we ship appearance:base for all in-page form controls at once before doing select and other ones with pickers it makes sense as an incremental opt-in for compatibility, but I don't think that chromium is going to ship appearance:base for other form controls before select.
Maybe a middle ground would be to make select::picker(select) { appearance:base; }
imply select { appearance:base; }
so you only have to write one of them instead of both?
We initially brought up appearance:base-select as a value for incremental opt-in for select first, and select::picker(select){appearance:base} works as an incremental opt-in for in-page elements first.
I'm starting to question the value of having an incremental opt-in at all if both of them have a significant burden on the developer. We could use css @supports to feature detect support for certain elements.
Anne and Una both seemed to say similar things about each solution, which is why I think we should just make it appearance:base on one element to get everything:
This avoids the cost to authors of having to learn and match a variety of base-* values.
Why force developers to remember both selectors that they will need to target, degrading the developer experience?
The CSS Working Group just discussed Styling form control pickers
.
I wanted to pull out the answer to this question: “Why force developers to remember both selectors that they will need to target [element itself and ::picker() pseudo-element], degrading the developer experience?”
The issue isn't that we can't feature detect. The incremental opt-in per picker type is for compat reasons. Authors will often use a more general selector than is needed then opt in, and expect it to continue to not to take effect on the elements it currently doesn't take effect on. But then we end up with "we cant ship appearance: base" on, say, date controls, because they weren't in the original set, and shipping that changes existing pages that weren't expecting it. Now we need a new keyword appearance: base-no-really-including-date-pickers. That's why we need an incremental opt in.
The reasons we split into in-page and not-in-page: First, we believe we can pull together the necessary standardisation/implementation work to do in-page controls within a reasonable amount of time, but styling pickers is a multi year project. Something we'll have to do incrementally. Second, it may be that developers want to style in-page controls to ensure they match the page's aesthetic, but don't mind the picker being native--either because they don't have the budget to do full styling of all the pickers, or because they prefer the OS controls (which may have abilities or affordances that in-page ones don't, for example, being able to pop out of the viewport). Pop-ups that have native styling are much less disruptive aesthetically than in-page controls that can't be styled (such as filepicker buttons), so it's a natural break point.
The reason we have ::picker()
with a bunch of identifiers is that we don't anticipate being able to tackle handling all of the pickers consistently and thoroughly all at once. We can make the argument optional after we've made them all styleable--in that case authors can just use ::picker() without the keywords--but this gives us a gradual transition towards that world, allowing us to ship in pieces.
(Many thanks to @keithamus for the excellent minutes.)
Thank you all for the great call today!
We didn't have time on the call today, but I wanted to re-affirm that I'm all for landing as many controls at once as possible to avoid having too many base-foo
keywords. That said, one thing I would like to ask @fantasai based on this statement:
fantasai: I think we at apple generally disagree we can't ship apperance:base all at once. We think its doable within the next year or two
What is your plan on how to accomplish this? We'd need to divide this work up asap across the teams to align on parts, pseudo elements, behaviors, and then produce the base stylesheet so that they can then be implemented across the numerous usecases that these components/controls provide. Happy to sync up in some other way to meaningfully put together a project plan as we'll need this regardless of how we intend to roll this out.
Thanks for the discussion everyone! I’d like to build a resolution based on fantasai’s comments at the end of the meeting:
fantasai: …In terms of select specifically, it's special, google's been working hard on it but it's also a form control where the picker and all components can be represented as elements in the page. ... most other form controls have pickers with UA magic ... it might be reasonable to ship appearance:base-select just for selects, while we work on the rest, then ship appearance:base for everything
I’d like to propose the following resolution:
appearance:base-select
opts-in both the in-page control and the picker for <select>
.::picker { appearance: base }
will be used for all form control elements (including <select>
) as an opt-in/incremental shipping plan, per Apple’s proposalappearance:base
will apply to the in-page parts of all form controls (including <select>
)That would mean base-select
has to remain a magical value. That doesn't seem good.
@annevk what do you propose as an alternative?
Making the opt-in for the picker separate as we had tentative agreement on initially. That's more compatible with the model we plan for the future and would allow base-select
to become an alias for base
in due course.
If I'm understanding correctly (I might not be), that revises the proposed resolutions to:
appearance:base
will apply to the in-page parts (only) of all form controls (including <select>
), and, to avoid forwards-compat problems, must ship simultaneously on all form controls.
::picker(keyword) { appearance: base }
will apply to form control pickers as an opt-in to styleable pickers of the named control type, with the control-type keyword allowing per-control-type incremental shipping of styleable pickers. To avoid forwards-compat problems, we will consider a keywordless variant only once all form controls can be opted in.
If appearance: base
on all in-page controls is not ready in time for <select>
, we may add appearance: base-select
whose behavior is equivalent to appearance: base
, but only applies to <select>
and its picker (::picker(select)
).
The CSS Working Group just discussed Styling form control pickers
.
If I'm understanding correctly (I might not be), that revises the proposed resolutions to:
* `appearance:base` will apply to the in-page parts (only) of all form controls (including `<select>`), and, to avoid forwards-compat problems, must ship simultaneously on all form controls.
I think Google was ok with this, with the caveat that they want appearance: base-select
, (and maybe appearance: base
?) to opt in both the button and the picker, but they wanted it to move to a separate issue.
* `::picker(keyword) { appearance: base }` will apply to form control pickers as an opt-in to styleable pickers of the named control type, with the control-type keyword allowing per-control-type incremental shipping of styleable pickers. To avoid forwards-compat problems, we will consider a keywordless variant only once all form controls can be opted in.
I think this is fine (not ideal tho), with one caveat, which is that we should either define how this would work when the control is not appearance: base
(which feels a bit of a can of worms), or explicitly state that it doesn't work (so ::picker(keyword) { appearance: base }
only does something if you've done foo { appearance: base }
).
* If `appearance: base` on all in-page controls is not ready in time for `<select>`, we may add `appearance: base-select` whose behavior is equivalent to `appearance: base`, but only applies to `<select>` and its picker (`::picker(select)`).
That means select { appearance: base-select }
would do something different to select { appearance: base }
, right? That seems a bit unfortunate... Would be good that, if we have the chance, we make appearance: base
apply to the picker as well at the same time?
After the discussion yesterday, and giving @annevk’s remarks some more thought, we actually agree that it seems best to have separate opt-in’s for the in-page control and the picker, even in the case of <select>
. So despite our comments yesterday, we’re in favor of adopting @fantasai’s proposed three bullet points, as-is. As mentioned by @emilio, we will have to work through exactly what happens in the two “mismatched” cases, where the picker is native and the in-page is “base”, or vice versa. That’ll take some work, but it seems tractable. It's possible we run into some roadblocks and we'll have to revisit those here. But otherwise we'll get started thinking about it. Your input would be appreciated!
Separately, there was a request made for Google to provide our own more-explicit “vision” for how to go about this form redesign process, and we’re working on that. More to come.
I am imagining a future in which authors may also provide custom pickers replacing the UA's pickers, even the system ones. E.g. an advanced color or date picker. So basically what people are working around right now due to the lack of stylability and customizability.
To stay consistent, it would be great if those pickers could be targeted the same way across all form controls providing pickers.
I currently don't have a concrete proposal for how that would work, though I wanted to mention it to keep future extensibility of this feature in mind.
Sebastian
::picker(identifier)
should only match when the in-page control is not using native appearance (i.e., not for appearance: auto
; only for base
and possibly none
if it can be done compatibly). At least I got the impression that we generally didn't want pseudo-elements to match in-page controls with native appearance (although we might have to make some legacy exceptions I suppose).
The other way around the picker would start out with native appearance until you set it to base
(and that's supported on the platform in question).
::picker(identifier)
should only match when the in-page control is not using native appearance (i.e., not forappearance: auto
; only forbase
and possiblynone
if it can be done compatibly). At least I got the impression that we generally didn't want pseudo-elements to match in-page controls with native appearance (although we might have to make some legacy exceptions I suppose).The other way around the picker would start out with native appearance until you set it to
base
(and that's supported on the platform in question).
Ahh ok, good, thanks for the clarification. So there's only one "mismatched" case: where the picker is native and the in-page is “base”. Not vice-versa.
Separately, there was a request made for Google to provide our own more-explicit “vision” for how to go about this form redesign process, and we’re working on that. More to come.
On this topic, we've written up some thoughts. Rather than post a giant comment on this thread, I've opened a fresh issue just to make it easier to read: https://github.com/w3c/csswg-drafts/issues/10804
After the discussion yesterday, and giving @annevk’s remarks some more thought, we actually agree that it seems best to have separate opt-in’s for the in-page control and the picker, even in the case of
<select>
. So despite our comments yesterday, we’re in favor of adopting @fantasai’s proposed three bullet points, as-is. As mentioned by @emilio, we will have to work through exactly what happens in the two “mismatched” cases, where the picker is native and the in-page is “base”, or vice versa. That’ll take some work, but it seems tractable. It's possible we run into some roadblocks and we'll have to revisit those here. But otherwise we'll get started thinking about it. Your input would be appreciated!
Proposed resolution: https://github.com/w3c/csswg-drafts/issues/10440#issuecomment-2303554166
The CSS Working Group just discussed Styling form control pickers
, and agreed to the following:
RESOLVED: `appearance:base` will apply to the in-page parts (only) of all form controls (including `<select>`), and, to avoid forwards-compat problems, must ship simultaneously on all form controls.
RESOLVED: `::picker(keyword) { appearance: base }` will apply to form control pickers as an opt-in to styleable pickers of the named control type, with the control-type keyword allowing per-control-type incremental shipping of styleable pickers. To avoid forwards-compat problems, we will consider a keywordless variant only once all form controls can be opted in.
RESOLVED: If appearance: base on all in-page controls is not ready in time for <select>, we may add appearance: base-select whose behavior is equivalent to appearance: base, but only applies to <select> and its picker (::picker(select)), individually.
I created a spec PR to define ::picker() here, please take a look: https://github.com/w3c/csswg-drafts/pull/10865
(nit) @josepharhar there is a duplicated =
in the production rule for ::picker()
that messes up its extraction as a selector by w3c/reffy
. I also suspect that you might want (edit: never mind, it probably matches ::picker(<type-selector>#)
but I have not read all the comments above.::part(<ident>+)
)
Thanks! I made a fix here: https://github.com/w3c/csswg-drafts/pull/10936
As part of the discussion around
appearance: base
colleagues and I presented a vision of how this could work. The idea outlined in that presentation is that stylability of form control pickers (the overlay box for select options, selecting a date, etc.) would have its own independent opt-in. This is because we think that form controls (excluding their pickers) can probably be mostly done all at once with a simpleappearance: base
switch and accompanying pseudo-elements. This avoids the cost to authors of having to learn and match a variety ofbase-*
values.Form control pickers however are quite a bit more involved and we expect it to take longer to tackle them and some we expect will never be stylable (e.g., the file picker). The idea is that when a form control uses
appearance: base
you can address its picker using::picker(form-control-identifier)
and independently set that toappearance: base
as well. E.g.,select, select::picker(select) { appearance:base }
would give you a stylable select.::picker(form-contorl-identifier)
would represent the outermost box of the form control picker and additional pseudo-elements will be needed to address the various pieces it consists of.