w3c / csswg-drafts

CSS Working Group Editor Drafts
https://drafts.csswg.org/
Other
4.5k stars 665 forks source link

[css-pseudo] ::indicator proposal for radio & checkbox controls #5914

Open gregwhitworth opened 3 years ago

gregwhitworth commented 3 years ago

I will follow up with the concrete proposal following the face-to-face presentation as I expect more than one issue to be spawned from the proposal.

astearns commented 3 years ago

@gregwhitworth do you have an idea of how long the presentation will be?

Just the presentation – I don’t expect to be able to determine ahead of time how long the discussion will take (though we may time-box it)

gregwhitworth commented 3 years ago

@astearns apologies, I meant to include that. I'd expect the presentation to be 15-20 minutes max. I'd like 2 resolutions as there will be 2 separate aspects to complete the proposal and a few open questions. So I think 45 mins, if possible would be worth while.

If we're pressed for time we could do the presentation and then I can file the separate issues, possibly pick up on Thursday or resolve at a later date. Obviously I'd prefer to connect it a bit for discussion/possible resolution but I know that these virtual ones are shorter.

css-meeting-bot commented 3 years ago

The CSS Working Group just discussed ::indicator pseudo-element.

The full IRC log of that discussion <TabAtkins> Topic: ::indicator pseudo-element
<TabAtkins> github: https://github.com/w3c/csswg-drafts/issues/5914
<TabAtkins> gregwhitworth: Proposal for an ::indicator pseudo
<TabAtkins> gregwhitworth: Problem is appearance of checkbox and radio controls vary greatly across browsers
<TabAtkins> [shows slide of different browser checkboxes]
<TabAtkins> gregwhitworth: Investigating a bunch of components, but checkbox/radio is #2 most cited problem
<TabAtkins> gregwhitworth: OpenUI is already working on the more general problem [describes general checkbox internal structure]
<TabAtkins> gregwhitworth: So right now I'm just talkinga bout the indicator itself
<TabAtkins> gregwhitworth: Proposal is ::indicator pseudo on input[type=checkbox] and [radio], selecting the check/dot in the element.
<TabAtkins> gregwhitworth: There are probably more indicators, like in range inputs, but not getting to those now, they're more complex.
<TabAtkins> gregwhitworth: We saw from accent-color that often the functionality and visuals of a radio/checkbox are fine, they just want to change colors. We don't necessarily want people to ahve to rebuild from the ground up, like appearance:none requires
<TabAtkins> gregwhitworth: So interop becomes the questions
<TabAtkins> gregwhitworth: We've got a lot of variation cross-brwoser currently, how do we let authors have meaningful customization
<TabAtkins> gregwhitworth: I propose there is a "base" keyword for 'appearance', specifying that the widget must render with a standard-defined way.
<TabAtkins> [slide shows a standardized checkbox]
<fantasai> Better idea: use the checkmark Unicode character
<TabAtkins> gregwhitworth: So there would literally be an <svg><path></svg> to render the checkbox, and can thus style with SVG properties
<florian> q+
<TabAtkins> gregwhitworth: So people asked why we needed to go to this level of detail
<TabAtkins> gregwhitworth: You don't know what's between the component root and the checkmark
<TabAtkins> gregwhitworth: Earlier with password-reveal, our internal structure was actually really complicated, with some funny details that limited authors
<TabAtkins> gregwhitworth: So learning from that, we wanted to give authors well-defined DOM/styles that they can work off of
<TabAtkins> gregwhitworth: But make it opt-in so everything stays with the native look-and-feel by default
<TabAtkins> gregwhitworth: I've built a web component that follows this model, and was able to do a ton of variations [shows off many variations from the same SVG base]
<TabAtkins> gregwhitworth: Other possibilities we discarded:
<TabAtkins> gregwhitworth: using background-image on ::indicator rather than inline SVG
<TabAtkins> gregwhitworth: using a unicode character inside ::Indicator
<TabAtkins> gregwhitworth: Both of these, you just don't get the same flexibility
<TabAtkins> gregwhitworth: And the interop of unicode characters happens to be very good, but bc it's text you're very limited in what you can control about it
<TabAtkins> gregwhitworth: So open questions
<leaverou> (Also it's trivial to generate an SVG with a single <text> that contains a unicode character)
<TabAtkins> gregwhitworth: What happens if you want to change the graphic entirely?
<TabAtkins> [shows off an inverse path on a shield]
<leaverou> Question: What would ::indicator { content: "✔️"; } do?
<TabAtkins> gregwhitworth: Tangential to this, being able to adjust viewBox via CSS would b euseful for this
<TabAtkins> gregwhitworth: So while this gets us 80% there, there are much more ocmplex scenarios
<TabAtkins> gregwhitworth: [shows off animation flipping from check to x]
<TabAtkins> gregwhitworth: OpenUI's more freeform solution gives you fuller control if you need it
<TabAtkins> gregwhitworth: So proposal is we add "appearance:base", and add ::indicator for checkbox/radio to select the check/dot.
<emilio> q+
<florian> q?
<TabAtkins> TabAtkins: Does ::indicator select the <svg> or the <path?
<TabAtkins> gregwhitworth: <svg>, so you can control the box
<TabAtkins> TabAtkins: Okay so we'll need structure there so you can apply 'd', since it doesn't inherit
<TabAtkins> gregwhitworth: Yeah, another pseudo, or [...]
<TabAtkins> leaverou: Woudl 'content' property work?
<TabAtkins> gregwhitworth: Haven't considered it, would need to think about it.
<fantasai> +1 leaverou , exactly what I was going to say
<TabAtkins> leaverou: I'd expect 'content' to work, as an author, the same way it works for list markers.
<TabAtkins> gregwhitworth: So you'd expect it to cancel out the built-in SVG?
<TabAtkins> leaverou: Yes
<TabAtkins> fantasai: One of the things on my q would be to say the same thing as Lea.
<Rossen_> q
<TabAtkins> fantasai: I'd say it should be just a pseudo with 'content' that the UA sets to an SVG
<TabAtkins> TabAtkins: If you rely solely on that, the only way to plumb in an SVG is via an iamge, and it's not stylable
<tantek> IMO a Unicode checkbox character wouldn't match anything that anyone implements, so that seems like a bad idea
<TabAtkins> fantasai: So we could default to text, but the author could then style in more things.
<TabAtkins> fantasai: It would be easy to adjust that.
<TabAtkins> gregwhitworth: Only stuff you could do with text
<nicole> +1 for having multiple ways of creating the glyph e.g. svg, font, image (but it wouldn't be a background image)
<tantek> we really shouldn't define things with defaults that are ugly
<fantasai> TabAtkins: Still can style using content easily, even if we use default is an SVG
<fantasai> TabAtkins: and can do a lot more if the default content is a standardized SVG
<TabAtkins> leaverou: And you don't need graphics software, can just write a data URL
<TabAtkins> gregwhitworth: and how do you get that checkmark image put together?
<tantek> agreed with gregwhitworth, don't make authors completely have to redefine a checkbox in order to tweak its styling
<TabAtkins> gregwhitworth: Without reaching for graphics software, can't adjust padding or sizing, can't add drop shadows, etc
<TabAtkins> leaverou: I thought with "appearance:base" you could just set all those properties
<TabAtkins> gregwhitworth: You can, but SVG still offers more power in graphical means
<jensimmons> q+
<TabAtkins> gregwhitworth: And I'm also trying to set up the convo for the range pseudo in the next convo, and they'll ahve more complex needs that wouldn't be handleable via text
<nicole> q+
<leaverou> q+
<TabAtkins> fantasai: wrt appearance:base, you were hinting in October, glad to see this
<tantek> No browsers's current checkboxes look like Unicode checkbox characters, seems like a hack to try to shoehorn like that or to explore that
<TabAtkins> fantasai: agree with premise. concern with doing it *right now* is that before we ship it, we'll need a structure for every html element
<astearns> ack fantasai
<TabAtkins> fantasai: If we ship for checkbox/radio and haven't figured out the other inputs, we'll have compat problems when we alter try to ship it for other inputs
<leaverou> +1 to what fantasai just said
<TabAtkins> gregwhitworth: what compat problems?
<tantek> +1 to what fantasai said, e.g. range control
<dholbert> (in particular if someone styles using `input {...}` as their selector, I imagine)
<TabAtkins> fantasai: If there's an effect on checkbox, but not *currently* on selects/files/etc, then people will apply the property too widely and it'll just do nothing so they won't notice; later when we define effects it'll change the page
<TabAtkins> gregwhitworth: It'll take a very long time to get all those structures in place...
<fantasai> TabAtkins: You're missing fantasa's point. Right now, it doesn't do anything on file input, people will apply it to all inputs to get the effect they want
<tantek> +1 good summary TabAtkins
<fantasai> TabAtkins: and then if you make it have an effect later, then that'll break pages
<astearns> q?
<fantasai> gregwhitworth: I would like to figure out how to do that in less than 10 years
<fantasai> TabAtkins: You could have different keywords per input type
<fantasai> TabAtkins: e.g. base-checkbox
<fantasai> TabAtkins: A little more awkward to use...
<fantasai> gregwhitworth: but maybe 10yrs later we can have just 'base'
<TabAtkins> fantasai: Another thing: naming it ::checked-indicator would make it clearer, ::indicator is super generic
<leaverou> Or just embrace the generic-ness and call it ::marker :))
<TabAtkins> gregwhitworth: I purposely didn't do the openui agenda for naming; we resolved on "indicator" there bc it's the generic word across component libraries
<tantek> +1 fantasai agreed, "indicator" sounds too generic, unless we actually define what it means for all controls that have "indicators", e.g. the disclosure triangle from summary/details!
<TabAtkins> fantasai: Sure, no problem with "indicator" itself, just that *by itself* it's not clear what it refers to
<TabAtkins> fantasai: Another topic: 'content' should apply so we can swap out for text or other images
<TabAtkins> fantasai: If you want the default contents to be a particular SVG, sure; but 'content' should still apply
<TabAtkins> gregwhitworth: Oh yeah sure, please open an issue for this
<TabAtkins> gregwhitworth: I like the idea of not having `[type=checkbox]::checkmark-indicator`
<leaverou> -1 to ::checked-indicator, as greg pointed out it would end up being too generic
<fantasai> ::checked
<fantasai> ::checked-indicator
<brandon> wouldn't ::indicator be targeted by the elements state? e.g. checked, indeterminate? which then makes its specific?
<leaverou> s/too generic/too repetitive/
<TabAtkins> fantasai: ::checked-indicator to match :checked
<TabAtkins> gregwhitworth: You'll be applying this alongside selector that already targets the element, so it should be obvious from the fuller selector context that this is a checkbox indicator
<Rossen_> q?
<TabAtkins> florian: I'm unsure how this - i like appearnce:base
<Rossen_> ack florian
<TabAtkins> florian: Unsur ehow styling works in UA stylesheet
<emilio> hah, was going to mention just this
<TabAtkins> florian: Can't select off of the property value
<TabAtkins> florian: But the UA probably does want to style appropriately based on the base value
<tantek> semi-agreed with florian, please don't overload 'appearance'
<TabAtkins> florian: So probably want some magic in the UA stylesheet for this
<Rossen_> q?
<emilio> actually, on checkboxes border doesn't suppress appearance
<TabAtkins> gregwhitworth: Yeah wehn I discussed with TabAtkins earlier we realized that magic would be necessary.
<tantek> q?
<fantasai> TabAtkins: It's a UA stylesheet in the shadow
<fantasai> florian: It's not just the parts inside that you're styling, but the checkbox element itself
<fantasai> fantasai: You can select the host element from shadow
<TabAtkins> florian: For existing checkbox/radio button, wonder if we could get away with ::before in that magic stylesheet
<TabAtkins> florian: I think if we were defaulting to unicode for checkbox, we could use ::before; if you want to default to an SVG that wouldn't fly...
<TabAtkins> florian: Anothe rpoint
<gregwhitworth> btw, here's a non-production web component that shows this: https://codepen.io/gregwhitworth/project/editor/754e0097edc1dd2e17617a36fed89d06
<TabAtkins> florian: For the controls that are reasonably stylable with appearance:none, people have styled them
<TabAtkins> florian: For the ones that are complex enough that "none" is unusable bc too much structure is needed, maybe we could define that "none" is the same as "base". Like for range controls
<TabAtkins> gregwhitworth: Yeah I was going to piggyback on "none" ages ago
<TabAtkins> florian: Also, +1 to tab's idea of specialized keywords
<Rossen_> ack emilio
<TabAtkins> emilio: Was gonna mention some of Florian's point, namely tweaking UA stylesheet is annoying
<TabAtkins> emilio: Right now, checkbox and radios are trickier than most, because appearance:none changes the box itself - it'll start respecting the display value, for example
<TabAtkins> emilio: For most controls we can explain it as shadow DOM
<TabAtkins> emilio: So Gecko has the ability to create elements at layout time; webkit/blink can't do that, they have the shadow present immediately and change the styling
<faceless2> present-
<TabAtkins> emilio: So it would be tricky, but overall this seems sane
<TabAtkins> emilio: Also right now, no browser creates a bunch of elements for checkboxes/radios, so if you have thousands that gain "base" it could slow things down
<TabAtkins> emilio: Right now they're just a single elemnt with a paint-time rendering
<TabAtkins> emilio: The shadow dom-in-stylesheet thing only works if the shadow dom is not there with appearance:auto
<TabAtkins> emilio: I think gecko can do it, but other browsers maybe not. IMplementability is tricky.
<TabAtkins> emilio: Borders in particular don't have florian's issue - nothing suppresses auto appearance for checkboxes
<astearns> ack jensimmons
<TabAtkins> jensimmons: I don't feel comfortable resolving on this yet
<Rossen_> ack jensimmons
<TabAtkins> jensimmons: I'm not sure what's actually bieng proposed yet - there was no code examples in the slides, ther'es no explainer...
<TabAtkins> jensimmons: Not even deatils needed, just big-picture of what are we doing, what's the plan for the future...
<fantasai> gregwhitworth, just send an attachment to www-archive@w3.org
<TabAtkins> gregwhitworth: I think those are all answere din the explainer, which I just can't expose publicly quite yet
<TabAtkins> Rossen_: Very valid feedback - getting the explainer out ahead of the discussion would have answered these questions
<TabAtkins> gregwhitworth: So inverting, would someone be against me writing a PR as we reveal the explainer, etc?
<TabAtkins> Rossen_: There's a lot more details than just PR - you'll go thru a TAG review, etc. It'll speed up once you get an explainer out.
<tantek> +1 to a much more clear / expanded explainer, rather than spec text
<Rossen_> ack nicole
<TabAtkins> nicole: I think this is a problem worth solving.
<TabAtkins> nicole: We did some looking around how appearance:none is currently used
<TabAtkins> nicole: We foudn another compat problem - people applied props that *only* work when appearance:none is on, but don't set appearance:none so those props dont' do anything
<TabAtkins> nicole: So they get backwards non-compat accidentally
<tantek> +1 nicole, use of appearance is confusing already, and I'd take that a step further: OpenUI should (must?) not use 'appearance' for any aspect of its design
<TabAtkins> Rossen_: Are youa skign about a fallback mechanism?
<TabAtkins> nicole: No, this feature triggers many things working, but if people use this now without (accidentally) turning this on, it makes things hard to change in the future
<TabAtkins> nicole: So if they set, say, height on it, which only works with appearnce:none, then that makes it hard for us to ever make 'height' work on default appearance for those elements
<gregwhitworth> Explainer: https://github.com/salesforce/standards-explainers/blob/master/indicator-psuedo/explainer.md
<TabAtkins> fantasai: But that doesn't happen unless you set appearance
<gregwhitworth> yay, it went public just in time :)
<Rossen_> q
<Rossen_> ack leaverou
<TabAtkins> nicole: Right, this was building on the earlier talk about this making it hard to ship "base" for othe relements in the future
<TabAtkins> leaverou: ABout where :indicator points
<TabAtkins> leaverou: If it points to the SVG, you can set storke/fill on the svg and those inherit
<TabAtkins> leaverou: Anothe rpoint, not sure about base-checkbox/base-radio, seems ocnfusing that you can apply them to othe rprops and they don't work
<TabAtkins> gregwhitworth: I already proposed that ::indicator is on the SVG
<TabAtkins> leaverou: Oh, ok
<tantek> +1 leaverou yes 'appearance' is a complete mess (again, I'm sorry). please stop attempting to expand it.
<Rossen_> ack fantasai
<TabAtkins> leaverou: Woudl also be good to have slides posted
<tantek> (I'm not queuing because leaverou already made the points I wanted to make)
<Rossen_> ack tantek
<Rossen_> ack TabAtkins
<fantasai> TabAtkins: need to point to path as well, because some properties don't inherit, like the path
<fantasai> TabAtkins: Most things can go onto svg, no problem
<fantasai> TabAtkins: Wrt base-checkbox etc. Reason those were weird and bad for appearance is because they were defined as "make this element look like this other thing" on any element
<fantasai> TabAtkins: They were supposed to do something, didn't, and wasn't clear what they were supposed to do at all
<gregwhitworth> https://www.irccloud.com/pastebin/S1etVZTK/
<gregwhitworth> jensimmons: ^
<fantasai> TabAtkins: The new values would only work on the matching elements, and would be well-defined what it does
<florian> q+
<fantasai> TabAtkins: doesn't have any effect on other things, will be interoperable
<fantasai> TabAtkins: doesn't have same problems as the previous appearance values
<fantasai> leaverou: Wrt SVG path, can just replace the SVG
<fantasai> TabAtkins: Then can't style it
<TabAtkins> florian: Also: the appearnace list had all the control *parts*, which made the property's list enormous, and different brwosers had different anatomies so their lists were different...
<Rossen_> ack florian
<TabAtkins> florian: Not trying to reproduce that, so this would be more manageable.
<TabAtkins> Rossen_: So wrapping up, Greg has dropped an explainer link.
<tantek> (aside: correction: appearance didn't have the control *parts* but rather had a hierarchy of types of controls, I can see how that could be confusing though)
<TabAtkins> Rossen_: It feels like people in the group want to be able to read the explainer before resolving on anything. Can you bring it back next week's call after people have a chance to read?
<TabAtkins> gregwhitworth: Yes, and please file issues as you find things.
<TabAtkins> <br dur=10min>
<TabAtkins> emilio, it would still work to have the SVG always inside the checkbox but display:none'd by default, right?
<TabAtkins> it woudl increase the weight of the elements, which you reaised as a separate concern
<tantek> FYI: original 'appearance' definition in case anyone wants the sordid history: https://www.w3.org/TR/2002/WD-css3-ui-20020802/#appearance
<TabAtkins> tantek: If you consider 'appearance' poisoned, nothing particularly wrong with minting a new property here, it's just that 'appearance' *already* has the right semantics.
<emilio> TabAtkins: hmmm, you mean with `appearance: none`? Having something like a shadow dom with the hidden svg could work I suspect, yeah
<TabAtkins> emilio: Dunno quite what you mean wrt appearance:none here, but probably, yes.
<emilio> TabAtkins: yeah, I meant that it wouldn't affect current uses of appearance: none
<TabAtkins> emilio: Then yes, definitely.
<TabAtkins> Also: I'm out for the day so kitty can go to the vet. See y'all Thursday!
<myles> ScribeNick: myles
gregwhitworth commented 3 years ago

The explainer can be found here: https://github.com/salesforce/standards-explainers/blob/master/indicator-psuedo/explainer.md

I've added some author example code based on valuable feedback from those on the call. As noted per action we will circle back to next week's agenda to discuss with a possible resolution of solving this problem in the CSSWG.

cc: @jensimmons @litherum @frivoal @LeaVerou @fantasai @tabatkins since you all provided the most feedback

zcorpan commented 3 years ago

@gregwhitworth why not make the proposed behavior for appearance: base be the behavior for appearance: none for radio buttons and checkboxes? Would it not be web compatible? There are likely some sites that use appearance: none plus a background image to show the checkmark, so this would show a double checkmark, though I don't know how common it is. Maybe it's even an acceptable change? The content would still work, just not rendered as originally intended. When styling form controls, that shouldn't come as a huge surprise I would think.

CSS UI says that widgets should be usable even with appearance: none, but checkboxes and radio buttons as implemented today aren't. https://drafts.csswg.org/css-ui/#appearance-semantics

(Feel free to split this into a new issue if you want to separate the discussion around appearance from ::indicator.)

cc @frivoal

gregwhitworth commented 3 years ago

@zcorpan @frivoal since your question is about appearance: base and not ::indicator I opened a separate issue. #5998

gregwhitworth commented 3 years ago

I updated the explainer based on @jensimmons and @frivoal feedback with author style examples and FAQs as it relates to the other solutions. @jensimmons @fantasai @frivoal @tabatkins @LeaVerou before I put this on the agenda about adopting this pseudo and I author normative text within the pseudo specification; are there any other clarifications that I can make to make the discussion as productive as possible? Thanks.