-
Notifications
You must be signed in to change notification settings - Fork 661
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[selectors][css-scoping] Should :host:has()
match?
#10693
Comments
Thanks for bringing the conversation here @tabatkins! I think the |
To clarify, are you saying that both In #10179 (comment) the idea is
|
I think it should match in both cases, just like the logical combination pseudos. The reason the host is featureless is because you can't control the markup of the host element, and so it's easy to write a selector you expect to only match the markup you control (in the shadow) and have it accidentally match the host element due to the outer page doing things you can't predict. This doesn't apply to The only way to get an unexpected match is if you just forget the host element exists at all (because you generally don't pay attention to it), but that's a brain fart, not an unpredictable situation. I think that's okay. In particular, writing an unqualified |
This would allow #10492 to be solved using |
Yes, that would work. |
(We should discuss this at the same time as #10179 fwiw; they're covering the same space.) |
Shouldn't this be about |
|
I think there are a few cases here that it would be great to untangle and specify. BackgroundThe spec defines Tree-Structural pseudo-classes, but it doesn't specifically distinguish the scope or relationship: ancestor or descendent. Similarly, :host() matches the argument in the host's "normal context," the scope in which the host itself exists, not its Shadow DOM. Additionally, there's a special carve out for the flat tree against which match Currently, DiscussionWhen Shadow DOM is involved, for the cases defined in the spec, only a descendent relationship is relevant to consider since this could be either via the light or shadow tree or both, the composed tree. The example noted above I believe only Using the functional Matching these against the shadow tree does seem useful as is suggested here, and using the non-functional syntax also seems to make sense
|
No. As I said in the initial comment,
It's not clear if you've read my later comment giving a more thorough explanation for why I think (And correct, |
@sorvell You seem to be confusing yourself about what it means for
|
Yeah, sorry, it wasn't clear to me that the intention was to have :host:has() match the contents of the shadow tree. I think it's a bit confusing that |
Thanks for the clarification, that makes sense. Overall, this would be a valuable feature to add. @tabatkins Do you think it makes sense to support |
I'm not sure I understand the confusion. You have two entirely separate subtrees, both rooted in the same element; the two syntaxes match against one or the other. It seems unremarkable to me that they would do different things, because that's what happens for every other possible selector as well: normal selectors match against the shadow tree (which is where the stylesheet in question lives, so that's exactly what you'd expect), and
Hm, yeah, that's workable under the same argument (it's only matching based on the non-host contents of the shadow, which are under the stylesheet author's control). It's only different from Not sure it's particularly useful - it seems a lot more likely that that component knows whether it's put anything inside the shadow tree, and in particular, a |
The CSS Working Group just discussed
The full IRC log of that discussion<TabAtkins> :host:has(.foo)<keithamus> TabAtkins: someone added tests in WPT combining :host:has. Some test well specified behaviour, but they added some tentative about using :host:has next to eachother in a compound selector <keithamus> ... tentatively wrote assuming this works and it matches the host element assuming a .foo is in the tree <keithamus> ... that doesn't work because :has doesn't match featureless elements in general <keithamus> ... the :has pseudo class should be able to match the host. Again, :host is featureless because authors of the shadow tree cannot predict the markup so it would have to be written defensively <emilio> q+ <keithamus> ... the :has pseudo class only matches based on descendents, ie stuff in the shadow tree thus already in control of the author <keithamus> ... so predictable behavior and no defensive coding <keithamus> ... there's also some examples this satisfies in the thread <TabAtkins> :host:has(.foo) and :has(.foo) both are allowed to match <keithamus> ... so :has should be added to the list of things to match the host element <keithamus> ... also unqualified :has(.foo) should be able to match the host element <keithamus> ... This is potentially confusing because no selectors currently match :host... nothing else can do this right now so it might not be expected. <keithamus> ... The benefit of allowing is that matching behavior becomes much more sensible if it is allowed to match unreservedly <emilio> Feels wrong that `*:has(..)` and `:has(..)` behaves differently <keithamus> ... it makes speccing more complex if not <keithamus> ... the simpler model, I think, is a little better <astearns> ack emilio <TabAtkins> *:is(:host) and :is(:host) already match different <keithamus> emilio: I get the use case of matching inside the shadow tree, I'm not sure I agree with making it match when not qualified. It feels wrong that * doesnt match but unqualified does. <keithamus> ... I guess you're right that's already the case per spec <keithamus> ... something matching host that doesnt contain :host feels bad <keithamus> ... I find it confusing. Especially as styles go outside your component <keithamus> ... either force :host or do a new pseudo or something <astearns> q+ <keithamus> ... I think I have a preference for enforcing :host especially as it doesn't change the behaviour for unqualified selectors <keithamus> TabAtkins: I suspect that unqualified :has is rare to non-existent as it could potentially match all elements. I would be surprised if it causes problems <keithamus> ... open to possibility that it would though <astearns> ack astearns <keithamus> astearns: I didn't go into the use cases but are the use cases presented for unqualified has that cannot be done with qualified has? Or is it ergonomics <keithamus> TabAtkins: purely ergonomics, purely a matter of ergonomics/spec complexity to make it work one way or another <keithamus> emilio: implementation complexity implies there is a benefit, then you can avoid looking at those selectors altogether <keithamus> TabAtkins: but you would still know which selectors are potentially able to match <keithamus> ... this expands the set of potential matches from things to the :host to things with unqualified :has <keithamus> emilio: :is also complicates, but if you have :host in the subject it can only match the host. :has can match random stuff in the tree <keithamus> emilio: I think unqualified :has matching :host is not great as an author <keithamus> ... other than my gut feeling I dont have strong arguments one way or another <keithamus> TabAtkins: are you implying theres a benefit to saying these selectors only apply to host or not? Being able to match either host or shadow tree is more complex? <keithamus> emilio: yeah. We can put the selector in a separate place to style the element, otherwise it's in the general place <keithamus> TabAtkins: the spec side, it means adding another clause to the conditions for what allows a compound selector to match a host element <keithamus> ... not a huge complexity but one more thing in the list <keithamus> emilio: spec or implementation complexity aside, I wonder what other authors think? A bare :has with random stuff inside accidentally matching the :host? <keithamus> astearns: the person who wrote the tests is not thinking about this accidentally perhaps <keithamus> ... I'd like to see what the valid use case is. Speaking personally, I think I'd like the use cases to justify this <keithamus> TabAtkins: for the feature entirely? Or needing :host to be spelled out? <keithamus> astearns: allowing a selector that doesn't explicitly use :host to match the host <keithamus> emilio: you claim the test author mentioned that? As far as I can tell they don't test that <keithamus> TabAtkins: all tests have :host:has. In the mindset of testing that :host matches appropriately. <keithamus> TabAtkins: I'm fine with resolving with emilio's ammendment <TabAtkins> :host:has() can match, :has() can't <keithamus> PROPOSED RESOLUTION: :host:has() can match, :has() can't <oriol> q+ <keithamus> oriol: I think this breaks the assumption from the previous issue <keithamus> ... when we have compound selector allowed to match host, here has wouldnt be allowed but the combination would <keithamus> ... so it breaks the general rule? <keithamus> TabAtkins: changing that rule to special case this would be part of that resolution <keithamus> oriol: so what would the general rule be? <keithamus> TabAtkins: I'll show the spec <keithamus> RESOLVED: :host:has() can match, :has() can't |
Support `:host:has()` case to check whether a shadow host element has a relationship between its shadow root node and shadow tree element: - w3c/csswg-drafts#10693 Normally, `:has()` checks relationship between its anchor element and the other elements in the same tree. But in `:host:has()` case, `:has()` checks relationship in the shadow tree of the anchor element. For example, `:host(.a):has(> div)` matches a shadow host element if the host has `a` class value and the shadow root of the host has a child div element. To cross tree boundary for testing selector and invalidating styles, this CL adds 'HasArgumentMatchInShadowTree' flag to the CSSSelector and sets the flag while parsing selectors. SelectorChecker and CheckPseudoHasArgumentTraversalIterator cross tree boundary for `:has()` argument test traversal if the flag is set. RuleInvalidationDataVisitor sets 'TreeBoundaryCrossing` invalidation-set flag for non-subject `:has()` if the flag is set. If StyleEngine reaches to a shadow host element while performing `:has()` invalidation, it invalidates the host element if the host is affected by `:has()` state change. Bug: 359758910 Change-Id: I69f0813deca4caefcff1f0b5ff8181ba67967a40
Support `:host:has()` case to check whether a shadow host element has a relationship between its shadow root node and shadow tree element: - w3c/csswg-drafts#10693 Normally, `:has()` checks relationship between its anchor element and the other elements in the same tree. But in `:host:has()` case, `:has()` checks relationship in the shadow tree of the anchor element. For example, `:host(.a):has(> div)` matches a shadow host element if the host has `a` class value and the shadow root of the host has a child div element. To cross tree boundary for testing selector and invalidating styles, this CL adds 'HasArgumentMatchInShadowTree' flag to the CSSSelector and sets the flag while parsing selectors. SelectorChecker and CheckPseudoHasArgumentTraversalIterator cross tree boundary for `:has()` argument test traversal if the flag is set. RuleInvalidationDataVisitor sets 'TreeBoundaryCrossing` invalidation-set flag for non-subject `:has()` if the flag is set. If StyleEngine reaches to a shadow host element while performing `:has()` invalidation, it invalidates the host element if the host is affected by `:has()` state change. Bug: 359758910 Change-Id: I69f0813deca4caefcff1f0b5ff8181ba67967a40 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5839398 Commit-Queue: Byungwoo Lee <blee@igalia.com> Reviewed-by: Rune Lillesveen <futhark@chromium.org> Cr-Commit-Position: refs/heads/main@{#1362877}
Support `:host:has()` case to check whether a shadow host element has a relationship between its shadow root node and shadow tree element: - w3c/csswg-drafts#10693 Normally, `:has()` checks relationship between its anchor element and the other elements in the same tree. But in `:host:has()` case, `:has()` checks relationship in the shadow tree of the anchor element. For example, `:host(.a):has(> div)` matches a shadow host element if the host has `a` class value and the shadow root of the host has a child div element. To cross tree boundary for testing selector and invalidating styles, this CL adds 'HasArgumentMatchInShadowTree' flag to the CSSSelector and sets the flag while parsing selectors. SelectorChecker and CheckPseudoHasArgumentTraversalIterator cross tree boundary for `:has()` argument test traversal if the flag is set. RuleInvalidationDataVisitor sets 'TreeBoundaryCrossing` invalidation-set flag for non-subject `:has()` if the flag is set. If StyleEngine reaches to a shadow host element while performing `:has()` invalidation, it invalidates the host element if the host is affected by `:has()` state change. Bug: 359758910 Change-Id: I69f0813deca4caefcff1f0b5ff8181ba67967a40 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5839398 Commit-Queue: Byungwoo Lee <blee@igalia.com> Reviewed-by: Rune Lillesveen <futhark@chromium.org> Cr-Commit-Position: refs/heads/main@{#1362877}
Automatic update from web-platform-tests Support `:host:has()` Support `:host:has()` case to check whether a shadow host element has a relationship between its shadow root node and shadow tree element: - w3c/csswg-drafts#10693 Normally, `:has()` checks relationship between its anchor element and the other elements in the same tree. But in `:host:has()` case, `:has()` checks relationship in the shadow tree of the anchor element. For example, `:host(.a):has(> div)` matches a shadow host element if the host has `a` class value and the shadow root of the host has a child div element. To cross tree boundary for testing selector and invalidating styles, this CL adds 'HasArgumentMatchInShadowTree' flag to the CSSSelector and sets the flag while parsing selectors. SelectorChecker and CheckPseudoHasArgumentTraversalIterator cross tree boundary for `:has()` argument test traversal if the flag is set. RuleInvalidationDataVisitor sets 'TreeBoundaryCrossing` invalidation-set flag for non-subject `:has()` if the flag is set. If StyleEngine reaches to a shadow host element while performing `:has()` invalidation, it invalidates the host element if the host is affected by `:has()` state change. Bug: 359758910 Change-Id: I69f0813deca4caefcff1f0b5ff8181ba67967a40 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5839398 Commit-Queue: Byungwoo Lee <blee@igalia.com> Reviewed-by: Rune Lillesveen <futhark@chromium.org> Cr-Commit-Position: refs/heads/main@{#1362877} -- wpt-commits: b40c843d18efb71ab2f1343ce53e82d06cdf7702 wpt-pr: 48383
Automatic update from web-platform-tests Support `:host:has()` Support `:host:has()` case to check whether a shadow host element has a relationship between its shadow root node and shadow tree element: - w3c/csswg-drafts#10693 Normally, `:has()` checks relationship between its anchor element and the other elements in the same tree. But in `:host:has()` case, `:has()` checks relationship in the shadow tree of the anchor element. For example, `:host(.a):has(> div)` matches a shadow host element if the host has `a` class value and the shadow root of the host has a child div element. To cross tree boundary for testing selector and invalidating styles, this CL adds 'HasArgumentMatchInShadowTree' flag to the CSSSelector and sets the flag while parsing selectors. SelectorChecker and CheckPseudoHasArgumentTraversalIterator cross tree boundary for `:has()` argument test traversal if the flag is set. RuleInvalidationDataVisitor sets 'TreeBoundaryCrossing` invalidation-set flag for non-subject `:has()` if the flag is set. If StyleEngine reaches to a shadow host element while performing `:has()` invalidation, it invalidates the host element if the host is affected by `:has()` state change. Bug: 359758910 Change-Id: I69f0813deca4caefcff1f0b5ff8181ba67967a40 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5839398 Commit-Queue: Byungwoo Lee <bleeigalia.com> Reviewed-by: Rune Lillesveen <futharkchromium.org> Cr-Commit-Position: refs/heads/main{#1362877} -- wpt-commits: b40c843d18efb71ab2f1343ce53e82d06cdf7702 wpt-pr: 48383 UltraBlame original commit: 7bd6a635665974228495e9f678104df70bdae688
Automatic update from web-platform-tests Support `:host:has()` Support `:host:has()` case to check whether a shadow host element has a relationship between its shadow root node and shadow tree element: - w3c/csswg-drafts#10693 Normally, `:has()` checks relationship between its anchor element and the other elements in the same tree. But in `:host:has()` case, `:has()` checks relationship in the shadow tree of the anchor element. For example, `:host(.a):has(> div)` matches a shadow host element if the host has `a` class value and the shadow root of the host has a child div element. To cross tree boundary for testing selector and invalidating styles, this CL adds 'HasArgumentMatchInShadowTree' flag to the CSSSelector and sets the flag while parsing selectors. SelectorChecker and CheckPseudoHasArgumentTraversalIterator cross tree boundary for `:has()` argument test traversal if the flag is set. RuleInvalidationDataVisitor sets 'TreeBoundaryCrossing` invalidation-set flag for non-subject `:has()` if the flag is set. If StyleEngine reaches to a shadow host element while performing `:has()` invalidation, it invalidates the host element if the host is affected by `:has()` state change. Bug: 359758910 Change-Id: I69f0813deca4caefcff1f0b5ff8181ba67967a40 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5839398 Commit-Queue: Byungwoo Lee <bleeigalia.com> Reviewed-by: Rune Lillesveen <futharkchromium.org> Cr-Commit-Position: refs/heads/main{#1362877} -- wpt-commits: b40c843d18efb71ab2f1343ce53e82d06cdf7702 wpt-pr: 48383 UltraBlame original commit: 7bd6a635665974228495e9f678104df70bdae688
Automatic update from web-platform-tests Support `:host:has()` Support `:host:has()` case to check whether a shadow host element has a relationship between its shadow root node and shadow tree element: - w3c/csswg-drafts#10693 Normally, `:has()` checks relationship between its anchor element and the other elements in the same tree. But in `:host:has()` case, `:has()` checks relationship in the shadow tree of the anchor element. For example, `:host(.a):has(> div)` matches a shadow host element if the host has `a` class value and the shadow root of the host has a child div element. To cross tree boundary for testing selector and invalidating styles, this CL adds 'HasArgumentMatchInShadowTree' flag to the CSSSelector and sets the flag while parsing selectors. SelectorChecker and CheckPseudoHasArgumentTraversalIterator cross tree boundary for `:has()` argument test traversal if the flag is set. RuleInvalidationDataVisitor sets 'TreeBoundaryCrossing` invalidation-set flag for non-subject `:has()` if the flag is set. If StyleEngine reaches to a shadow host element while performing `:has()` invalidation, it invalidates the host element if the host is affected by `:has()` state change. Bug: 359758910 Change-Id: I69f0813deca4caefcff1f0b5ff8181ba67967a40 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5839398 Commit-Queue: Byungwoo Lee <blee@igalia.com> Reviewed-by: Rune Lillesveen <futhark@chromium.org> Cr-Commit-Position: refs/heads/main@{#1362877} -- wpt-commits: b40c843d18efb71ab2f1343ce53e82d06cdf7702 wpt-pr: 48383
Automatic update from web-platform-tests Support `:host:has()` Support `:host:has()` case to check whether a shadow host element has a relationship between its shadow root node and shadow tree element: - w3c/csswg-drafts#10693 Normally, `:has()` checks relationship between its anchor element and the other elements in the same tree. But in `:host:has()` case, `:has()` checks relationship in the shadow tree of the anchor element. For example, `:host(.a):has(> div)` matches a shadow host element if the host has `a` class value and the shadow root of the host has a child div element. To cross tree boundary for testing selector and invalidating styles, this CL adds 'HasArgumentMatchInShadowTree' flag to the CSSSelector and sets the flag while parsing selectors. SelectorChecker and CheckPseudoHasArgumentTraversalIterator cross tree boundary for `:has()` argument test traversal if the flag is set. RuleInvalidationDataVisitor sets 'TreeBoundaryCrossing` invalidation-set flag for non-subject `:has()` if the flag is set. If StyleEngine reaches to a shadow host element while performing `:has()` invalidation, it invalidates the host element if the host is affected by `:has()` state change. Bug: 359758910 Change-Id: I69f0813deca4caefcff1f0b5ff8181ba67967a40 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5839398 Commit-Queue: Byungwoo Lee <blee@igalia.com> Reviewed-by: Rune Lillesveen <futhark@chromium.org> Cr-Commit-Position: refs/heads/main@{#1362877} -- wpt-commits: b40c843d18efb71ab2f1343ce53e82d06cdf7702 wpt-pr: 48383
Automatic update from web-platform-tests Support `:host:has()` Support `:host:has()` case to check whether a shadow host element has a relationship between its shadow root node and shadow tree element: - w3c/csswg-drafts#10693 Normally, `:has()` checks relationship between its anchor element and the other elements in the same tree. But in `:host:has()` case, `:has()` checks relationship in the shadow tree of the anchor element. For example, `:host(.a):has(> div)` matches a shadow host element if the host has `a` class value and the shadow root of the host has a child div element. To cross tree boundary for testing selector and invalidating styles, this CL adds 'HasArgumentMatchInShadowTree' flag to the CSSSelector and sets the flag while parsing selectors. SelectorChecker and CheckPseudoHasArgumentTraversalIterator cross tree boundary for `:has()` argument test traversal if the flag is set. RuleInvalidationDataVisitor sets 'TreeBoundaryCrossing` invalidation-set flag for non-subject `:has()` if the flag is set. If StyleEngine reaches to a shadow host element while performing `:has()` invalidation, it invalidates the host element if the host is affected by `:has()` state change. Bug: 359758910 Change-Id: I69f0813deca4caefcff1f0b5ff8181ba67967a40 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5839398 Commit-Queue: Byungwoo Lee <bleeigalia.com> Reviewed-by: Rune Lillesveen <futharkchromium.org> Cr-Commit-Position: refs/heads/main{#1362877} -- wpt-commits: b40c843d18efb71ab2f1343ce53e82d06cdf7702 wpt-pr: 48383 UltraBlame original commit: 7bd6a635665974228495e9f678104df70bdae688
In web-platform-tests/wpt#47441 a few tentative tests are suggested that test whether
:host:has(...)
works. The test author correctly notes that this isn't currently specified to work - only the logical combination pseudo-classes are allowed to match featureless elements and:has()
, while defined in the "logical combination" section, isn't on the list of logical combo pseudo-classes.I agree with the tester, tho, that this should work.
:host h1
works just fine, so:host:has(h1)
should work the same. I suggest that we add:has()
to the list of pseudo-classes allowed to work on featureless elements.(Note the first few tests in the WPT PR are testing the different scenario of
:host(:has(...))
, which is already well-defined to match, in a different way to what's discussed here. I'm talking about the latter three which are marked "tentative" in their filenames.)The text was updated successfully, but these errors were encountered: