-
Notifications
You must be signed in to change notification settings - Fork 758
Description
tldr: We should allow part names to also be selected as full custom pseudo-elements names, a la my-component::--heading in addition to my-component::part(heading).
In the Web Components virtual f2f today, we discussed custom pseudo-classes. In the thread about :state(foo) vs :--foo syntax, Maciej brought up the reasonable point that switching away from :state() to :--foo, but leaving parts as ::part(), is inconsistent.
I explained the reason behind maintaining ::part(): due to CSS's bad syntax choices in the past, pseudo-element syntax implicitly contains a combinator, moving the subject of the selector into the element's "pseudo children"; as a result, you can't stack pseudo-elements to apply multiple conditions to a single pseudo-element. However, we want to allow that for parts - we want a calendar widget to be able to expose day elements for styling with something like part="day weekend saturday week-1 us-holiday", and let stylesheets select on a combination of those qualities, like ::part(day weekend us-holiday)
However, Maciej's point is still valid! Also, people have wanted ::--foo syntax, to mirror normal pseudo-elements, and things like UA pseudo-elements (::-webkit-scrollbar-thumb, for example).
Jan's idea was to unify these - allow parts to be selected either with ::part(foo) or with ::--foo; if you only need to select on one property, you can use the more direct form, but ::part() remains if you have more complex selecting needs. This received general approval in the call, and I think it's a good idea personally. General thoughts?
I think there's one important detail to decide, which is how to handle existing part='' content. In general, CSSWG has made the decision that dashed-idents should be used consistently thruout APIs: you reference the --foo custom property with var(--foo), not var(foo), etc. In other words, the -- is part of the name, not a context-specific indicator of custom-ness.
Currently, tho, part='' allows any ident, not just dashed-idents. How should we deal with this? I see a few options:
-
(I don't like this, it's bad, but for completeness:)
partis unchanged. If you definepart="foo", you can reference it as::part(foo)or::--foo. In other words, the -- is a context-specific indicator of custom-ness, but is not used when defining it, or referencing in::part(). (Note: if you saidpart="--foo", it would be referenceable as::part(--foo)or::----foo`.)This is backwards-compatible with existing code, but breaks consistency with how dashed-ident features are used everywhere else in CSS, both currently and planned. The component author doesn't make a choice on how to expose things, but the component user is presented with two fairly different names to refer to.
-
partis unchanged. If you define a part as a dashed-ident, it can be referred to as a top-level pseudo-element. That is, givenpart="foo --bar", you can use::part(foo),::part(--bar), or::--barvalidly.::--foowill not match, nor will::foo.This is backwards-compatible with existing code, and consistent with CSS design principles for dashed-idents. However, it imposes a choice on component authors of whether they want to expose parts as top-level pseudos or only within
::part(). (There might be a good reason to make this distinction? Unsure, but I suspect not.) -
We restrict
partto only allow dashed-idents.part="foo --bar"only defines one part name,--bar, which can be referenced as either::part(--bar)or::--bar. (The "foo" is ignored, as part of our forward-compatible error handling that silently drops things that aren't understood.)This is not backwards-compatible; virtually all existing content would become invalid and stop defining parts. However, it means there's no choice on the component author's side, and the component user has a closer relationship in the two syntaxes.
I slightly lean toward 3, but I'm unsure how much back-compat pain we want to take on. I'm fine with 2 if it's preferred by others. I'll fight against 1, it's terrible.