Repository navigation
[css-pseudo] clarify paired-cascading behavior #6386
Copy link
Copy link
Closed
Labels
Closed Accepted by CSSWG ResolutionChanges backed by a CSSWG resolution.Changes backed by a CSSWG resolution.css-pseudo-4Current WorkCurrent Work
Description
https://drafts.csswg.org/css-pseudo-4/#highlight-cascade
The UA must use its own highlight colors for ::selection only when neither color nor background-color has been specified by the author.
I think this sentence could be worded more precisely:
- Does “use” mean used value? This is mostly theoretical, because the spec doesn’t expose highlight pseudos to getComputedStyle, but I think it might affect what the devtools story looks like.
- Does “highlight colors” refer to a set of properties, and if so, which properties? My best guess is that color and background-color are included (because those are the ones with defaults in practice), and maybe stroke-color and fill-color too (wpt)? But what about text-{decoration,emphasis,shadow}?
- Do we really mean “for ::selection” only, or did we intend this for all highlight pseudos? The note suggests this rule exists for compatibility with existing ::selection impls, but ::target-text often has a default background-color too (see also [css-highlight-api] Need clarification on expected default values for style properties #6375).
- Do we really mean “neither color nor background-color” only, or any of the applicable properties? Note that the former would be inconsistent with existing impl behavior. For example, in Chrome and Firefox, setting text-shadow (even to none) also disables the usual default background-color (example).
- What does “specified by the author” mean? My best guess is that “specified by the author” means “cascaded value exists, and its origin was not the user agent”. Not specified as in specified value, which iiuc always exists due to defaulting (to transparent for background-color).
- How do we reconcile that with unset and revert? I feel like initial and inherit count as “specified by the author”, because the cascaded and specified values clearly exist for both, but for unset and revert, doesn’t it depend on whether we’re looking “before” or “after” they take effect?
- Do all properties become inherited for the purposes of deciding if unset should mean initial or inherit? I thought they did at first, but my Chromium colleagues have now convinced me that they don’t, given the “regardless” in “regardless of whether that property is an inherited property”.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
Closed Accepted by CSSWG ResolutionChanges backed by a CSSWG resolution.Changes backed by a CSSWG resolution.css-pseudo-4Current WorkCurrent Work
Activity
meyerweb commentedon Jun 16, 2021
/cc @fantasai @astearns @therealglazou
delan commentedon Jul 15, 2021
@fantasai any chance you can share your thoughts? Questions 1 through 5 represent everything I was directly unsure about with that part of the spec, while questions 6 and 7 might just reflect my poor understanding of explicit defaulting (sorry). Thanks!
fantasai commentedon Jul 24, 2021
Hmm, I guess this is underdefined. It could even affect the computed value without causing any problems. Probably the answer here should be whatever seems convenient to implementers.
It was intended to refer to using the UA's chosen values for selection foreground and background (its “highlight colors”) as color and background-color, matching the set of properties of question 4.
(This should probably say that the UA uses Highlight and HighlightText, actually, now that we have defined these colors as their own keywords.)
Currently, we do mean ::selection only. It's a very weird behavior, from the perspective of the cascade. If you and @emilio both think it should be extended to ::target-text, we can consider it.
Yes. Only if 'color' or 'background-color' is set, specifically and intentionally. There was a discussion about how this doesn't match current implementations earlier... we run into problems as new properties are introduced unless we restrict it thus. Suppose, for example, implementation A supports text-shadow on ::selection and implementation B does not. If implementation B cancels its highight colors when it sees the text-shadow declaration, then when an author specifies text-shadow as the only highlight indication, then the highlights will be visible in implementation A and invisible in implementation B.
Right, this is the intent. Again, we have this weird cascading behavior because of compat. If you have suggestions on how to simplify without breaking compat, I'd be happy to spec such changes.
I think if the author wrote
they're looking for the behavior that would have resulted from not writing anything, and it would be good if we can provide that.
I think they would have to, for 'unset' to have the expected effect of erasing any previous declaration.
Thanks for the good questions...
frivoal commentedon Jul 25, 2021
I'm not sure. I think it should be used value. One reason is that the UA could decide to paint something fancier than what you could achieve with ordinary values. Using computed values would mean that we need to figure out what that means for animations. If we're in used-value land, that's not a concern.
Even if you're not using fancy things that cannot be represented as a color value, transitions might still be tricky, as I suspect we'd need some special-case code to handle this pair of properties that change value when either of them is asigned something, and that doesn't seem important enough to be worth handling.
Shoving all that to used value means we don't get transitions, and we don't have to deal with any of that.
delan commentedon Jul 27, 2021
Thanks @fantasai + @frivoal for the thorough answers! So to remind myself when I get back into my impl work:
I’ve just realised that there’s a third origin between author and UA: the user origin. While it might be possible to extend paired cascade so that it applies to both legs of the cascade (UA-to-user and user-to-author), what I’ve seen of Blink’s impl makes me instead prefer to change “specified by the author” to “specified by other origins”. I think this would also make revert behave more consistently with the idea of rolling back the cascade.
I can’t speak for Emilio, but I’m leaning slightly towards extending it to all highlights. To me it depends on which inconsistency will annoy authors more: all highlights (effectively ::selection and ::target-text with typical UA defaults) having paired cascade but nothing else, or ::selection having paired cascade but nothing else.
The impl for Blink won’t be much harder either way, and while the rule itself provides a non-zero benefit (making it harder to accidentally create illegible highlight colors), I think I’m not alone in saying that the benefit wouldn’t have been big enough for us to put this in the spec if it weren’t for compat.
So yeah, I would say extend it?
andruud commentedon Jul 27, 2021
A bit of work went into cleaning up the previous "specified/modified by the author" mess we had related to disabling of appearance:auto. We have sane behavior there now which is basically: any value except
revert(but includingunset) counts as "specified by the author". We should stick to the same here.Loirooriol commentedon Jul 27, 2021
What does
inheritmean in highlight pseudo-elements? The spec saysSo if the cascaded value is
inherit, then it doesn't inherit from the parent highlight? It inherits from the originating element?I would probably expect it to instead use the custom inheritance chain, i.e. inherit from the corresponding highlight pseudo-element of its originating element’s parent element.
delan commentedon Jul 29, 2021
To expand on this, after discussing it with @andruud: in Blink, we decided to treat unset as author-specified when rendering non-disregarded properties for widgets with native appearance (auto), at least in part because it gives authors the option of setting something to inherit-or-initial, which might be different to the UA stylesheet and/or native appearance. This is distinct from revert, where we would roll back to UA defaults (or user styles, if any).
While none of that is really specified behaviour, we thought the choice made more sense there, and we’re primarily trying to avoid a situation where we have two different concepts of “specified by the author/non-UA” with subtle differences.
Loirooriol commentedon Jul 29, 2021
(Context for
revertreverting to native UA rendering: #4777 (comment))delan commentedon Aug 30, 2021
Interesting @Loirooriol, that didn’t even cross my mind. I agree that inherit should use the parent highlight just like we do for defaulting, I guess this is worth clarifying in the spec.
Thanks for that! So from reading that, in appearance, both Blink and Gecko treat unset as specified and revert as not-specified, and andruud argues that this was a good choice there. As for specified by whom, Gecko does author or animation or transition, while Blink currently does author only (but we intend to align with Gecko). No one has said anything about the user origin.
Of course, none of these details about appearance are really specified, but ultimately we want to figure out how to avoid having two concepts of “native/UA-default if specified” in our impl.
To recap without the “uncontested” stuff, we’re left with these opinions so far:
1. used value or computed value? fantasai says either, frivoal says used.
3. ::selection only or all highlights (spec says ::selection)? fantasai defers to impls, i say all (weakly), @emilio?
5. specified by whom (spec says author)? i say all, appearance impls converging on author/animation/transition.
6. should unset count as specified (in css-cascade terms, yes means “treated as inherit/initial” wins, no means “effectively erases” wins)? fantasai says no, andruud says yes.
8. should revert count as specified? fantasai says no, andruud says no.
(hopefully i haven’t misrepresented anyone, if so please correct me)
emilio commentedon Aug 30, 2021
I think right now this is a used-value time operation in Gecko, it's not only theoretical. e.g. the selection background might be inverted based on contrast with the closest non-transparent background color. That's something pretty hard to do at computed value time, if possible at all.
I think conceptually all, but same concerns about performance apply to this approach (to
::selectionas well).Wdym with "all" here? "author/animation/transition"? Or something else? I think that makes the most sense.
I agree with @andruud here, I think.
unsetis a value specified by the author. It's the same as the author specifying the initial value for non-inherited properties, orinheritfor inherited ones.revertexplicitly reverts to the previous origin.emilio commentedon Aug 30, 2021
@delan clarified that she meant "all" as "user/author/animation/transition". I guess that may make some sense for highlights as opposed to appearance, but if possible I'd like to keep just one concept for this.
delan commentedon Sep 9, 2021
Good point, that makes the spec lawyer in me wonder if “UA must use its own […] only when” forbids UA changes to the author’s highlight colors, like Gecko inverting selection backgrounds or Safari on macOS making opaque selection backgrounds translucent (demo). Blink (and previously WebKit) invert selection backgrounds too, just based on foreground similarity rather than surrounding backgrounds, which is starting to create problems for reftests (cc @mrego).
I believe the spec didn’t intend to forbid these, but I think that’s something worth making more explicit after this issue.
Yeah, performance is definitely something I’m still unsure about. For example, my initial Blink impl won’t make Select All slower, but it will make element style recalc slower, and there could be a big penalty for existing content with universal ::selection rules (looking into mitigations soon). I suppose this issue (except q7) is independent of the inheritance stuff though.
Maybe we should think about which to keep based on how that will affect stylesheets at each origin. I tried to reason about this but didn’t get very far, because I couldn’t figure out how to play with user origin styles in any of the browsers I use.
delan commentedon Sep 23, 2021
I’ve never made substantive spec changes before, but I’ve proposed a way to explain this behaviour (and edits for the other points discussed in this issue) in #6665. I ended up using a cascaded-value-based model like my guess above, but I’ve since found a stronger reason (than the one above) not to use a specified-value model: inherit and initial don’t exist as specified values, which would make them impossible to explain.
2 remaining items
fantasai commentedon Nov 30, 2021
@delan Wrt which origins disable UA defaults, I'm OK with @emilio's answer as well. Though including the Transitions origin seems weird to me, what if the UA rules want to transition between two styles? That'll still end up in the Transitions origin. Wrt unset/revert, the logic proposed makes sense to me.
UA cannot do these weird things when the author has specified colors. They have to use the author-specified colors with no modification. But when using UA-chosen colors, they can choose anything.
Run a search for "Firefox userContent.css".
delan commentedon Dec 3, 2021
So reading these few comments, I think the same choice was made for ‘appearance’ because neither Gecko nor Blink are able to tell the difference between a UA transition and an author transition, they are both just transitions? But like ‘appearance’, making transitions suppress UA defaults here improves the experience for authors at the expense of breaking UA transitions? Not sure if I’ve understood that correctly, maybe @andruud and @emilio can correct me.
Thanks! I’ll play around with the user origin, then see if I can make a case for one or the other.
That would definitely make the reftest story easier, but I don’t think we can allow Safari to paint ::selection as a translucent “wash” and forbid Safari from making opaque ::selection backgrounds translucent.
@mrego pointed out that the Gecko example actually only happens under UA-chosen highlight colors, so no worries there. Let’s discuss Safari in #6853 to avoid making this issue even longer.
delan commentedon Dec 8, 2021
Paired cascade affects used values only, while transitions (and animations) operate in computed value space, so regardless of whether the transition (and/or animation) origin is included, UA transitions (and animations) will behave as if UA default highlight colors were suppressed while interpolating. If anything, including the transition origin allows UA transitions to work, because if the transition origin didn’t suppress default highlight colors, we would use default highlight colors during any UA transition.
@andruud says there are potentially still some problems with treating UA/user-originating transition and animation styles as “author specified” for native appearance, so if that ends up changing again, we might want to change it here accordingly, but otherwise I don’t think this is a problem for highlight paired cascade.
Yeah, currently in Blink we have no way to tell if some {transition,animation}-origin styles are the result of author transition or UA transition, though we also have no need to do so, as long as our UA stylesheets don’t use any affected transitions/animations.
delan commentedon Dec 8, 2021
So there’s no concept of user default highlight colors, only the UA has default highlight colors, and I don’t expect that to change. But the user stylesheet can set highlight colors, so the main question is, should user highlight colors suppress UA defaults?
If they don’t (as currently proposed), user styles can change one highlight color while leaving the other one as the default highlight color. This is how Firefox currently works. For example, if the default highlight colors are white on blue, and userContent.css says ::selection has a green background, an unstyled page would have white-on-green selections, not initial-on-green, because the default highlight foreground ‘color’ would not be suppressed.
If they do, user styles that change one highlight color will make the other one default to initial. Using the example above (default white-on-blue, plus user background of green), an unstyled page would have initial-on-green selections (typically black-on-green), because the default white foreground ‘color’ would be suppressed.
I don’t really have an opinion on which of those behaviours is better.
However! Either way, setting either of the highlight colors in user styles “splits” paired cascade for authors. Using the example above (default white-on-blue, plus user background of green), if the author also only sets ‘background-color’, then ‘color’ is ‘initial’ as usual. But otherwise, ‘background-color’ is green, regardless of whether the author sets ‘color’. This is again how Firefox currently works. This smells kinda awkward, but I’m not sure if it’s actually problematic.
delan commentedon Dec 8, 2021
(summary for meeting)
css-meeting-bot commentedon Dec 15, 2021
The CSS Working Group just discussed
Paired Cascading of Highlight color/bgcolor, and agreed to the following:RESOLVED: Author origin rules, and not user-origin rules, trigger paired cascade fallbackThe full IRC log of that discussion
<fantasai_> Topic: Paired Cascading of Highlight color/bgcolor<fantasai_> github: https://github.com//issues/6386
<fantasai_> delan: for compat reasons, highlights have a "paired cascade", at least for ::selection (but we decided to apply to all)
<fantasai_> delan: for background-color and color
<fantasai_> delan: if you have some browser default colors for ::selection, e.g. white on blue
<fantasai_> delan: if you then go and set one of those two properties, then both of the defaults get suppressed
<delan> ::selection { background: yellow; }
<fantasai_> delan: defaulting to their initial value
<fantasai_> delan: e.g. if you set selection's background to yellow, then the default foreground color at used value time is no longer going to be white
<fantasai_> delan: This issue was pretty big, I asked 7 questions about it in the issue
<fantasai_> delan: pretty much none of the questions have disagreement in the issue
<fantasai_> delan: the main open question is, which origins should this apply to?
<fantasai_> delan: Original spec text says that when author sets one of these two properties, then we suppress highlight color
<fantasai_> delan: but there's also animation and transition origins, and also user orgin
<fantasai_> delan: will talk about aimation and transition first
<fantasai_> delan: I think it doesn't matter whether animation or transition is included in this rule or not
<fantasai_> delan: we used to think it mattered for consistency with 'appearance', but I realized it doesn't matter because the animation and transition properties are not applicable for highlights
<fantasai_> delan: so as far as I'm aware, can't use them in highlights
<fantasai_> emilio: I think ?? you should be able to
<fantasai_> emilio: don't know if propertly supported, though
<fantasai_> dholbert: can a property that is inherited be animated or transitioned?
<fantasai_> delan: Wondering if it is allowed by the spec right now
<fantasai_> delan: if not allowed, then doesn't matter whether those origins included in this rule
<fantasai_> delan: at least until they become allowed
<fantasai_> florian: I believe delan is right, not part of the list of allowed properties
<fantasai_> delan: no way for some way for them to sneak in, despite being applicable properties?
<fantasai_> florian: I don't think we designed one
<delan> s/being/not being/
<fantasai_> dholbert: if animate color of parent, and it inherits through?
<dholbert> s/dholbert/emilio/
<fantasai_> fantasai_: That wouldn't be in the animation or transition origin on the highlight itself
<fantasai_> delan: if not possible to come into highlight overlay, and it doesn't matter
<fantasai_> florian: I think we should talk some other day whether they should, but until they do...
<fantasai_> delan: For the user origin, I did some playing around with user style sheets
<fantasai_> delan: afaict, the question here about user origin and paired cascade comes down to
<fantasai_> delan: if the user sets one of the two properties (bg color or color) in their user style sheet
<fantasai_> delan: do we want that to suppress the UA default for the other property or do we want it to not suppress it and leave the other property as UA-default
<fantasai_> florian: Can implementations guide us? This rule was just for compat
<fantasai_> emilio: I don't think there's any compat requirements on user origin
<fantasai_> emilio: User origins don't disable appearance, so let's follow that precedent
<fantasai_> fantasai_: My reading is that we really don't care, so we should do whatever is easiest
<fantasai_> delan: works out
<fantasai_> delan: even if you go with compat angle, it doesn't suppress default UA colors in Firefox
<fantasai_> Rossen: other opinions?
<fantasai_> RESOLVED: Author origin rules, and not user-origin rules, trigger paired cascade fallback
<fantasai_> delan: In the issue, we all agree on the other 7 questions
<fantasai_> delan: do we need resolutions?
<fantasai_> fantasai_: IIRC they're minor enough that I'd close them under Editor Discretion
update origins considered by paired cascade for resolution in w3c#6386
[css-pseudo] clarify paired cascade (#6386 + #6779 + #6774 + #7837) (#…
delan commentedon Oct 6, 2022
#6665 includes the answers to these questions in the spec. Thanks everyone!