-
Notifications
You must be signed in to change notification settings - Fork 660
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
[css-cascade-6] Scoped selectors shouldn't match the scope root unless explicitly requested with :scope? #8377
Comments
The other way to exclude the scope is just Note that the host element is unmatchable except by the I lean weakly towards "no change", then. |
Not quite - though your point may still stand. Only the matched element needs to be in scope, the rest of the scoped selector matches unrestricted – so you would need to explicitly list the scope root itself as the ancestor: |
I suppose |
Oh duh, right. Well yeah, at least the Nesting version would work by default, yeah. |
How? /* relative selector is not allowed here */
> * {}
@scope (div.scope) {
/* relative selector is not allowed here */
> * {}
}
.bar
@scope (div.scope) {
/* relative selector IS allowed here, but & is `.bar` */
> * {}
}
} In the last example it would be |
Thanks @mirisuzanne for posting this issue. It was still on my todo, but glad to see you posted it (in a more articulate way than I ever could). The idea came up after playing with the With regular One thing that might seem a bit weird in this scenario is that there’s only one pseudo available to select the start boundary, not one to select the lower boundary. Miriam had arguments that this wasn’t too big of a problem. |
@romainmenke my understanding was that we had decided to make
I suppose it's not clear to me if you're allowed to leave the
@bramus Yeah, that might be a little odd, and may point to a |
I suggested to allow relative selectors in more contexts here : #8010 |
Digging into this, I'm convinced that authors will expect 'nested by default' behavior - which would better match how nesting works as well. To get there, we don't actually want to remove the scope root from the scope. We only want to imply that the scoped element is prepended as an ancestor, unless otherwise explicitly placed in a selector. This would bring This is a bit different from the 'virtual' scoping root behavior defined for dom fragments, the primary use of If we go that rout, it's not an exact parallel with |
Yeah, that restriction is only because doc fragments aren't elements, and selectors are defined to operate over elements. It shouldn't be taken as a more general restriction on :scope. |
In that case, my proposed resolution is that scoped selectors are implicitly descendants of the scope root element, unless I think something like |
Agenda+ to resolve on that change. |
+1, this is great. I think it opens up some new ways of optimizing.
This means we'll add something like the "nest-containing" concept but for scoped selectors, right? |
I suppose, yeah. A little more annoying to do the "if you see something that even resembles a :scope, mark the selector and preserve it in forgiving lists", but not untenable. Hm, this will require a small edit to Selectors, tho - the restriction against matching the scoping root itself is in fact baked into the matching algorithm, so I'll need to account for this there. |
@tabatkins can you clarify that 'anything that even resembles a :scope'? Is that meant to account for using The main difference I see here is that |
"contains the nesting selector" has that special text where we look for an & token in the original tokens, before potentially throwing anything out for invalidity, so
As currently specced, |
That makes sense, yes. For matching semantics with
Laying out those options, I think 2a is the one that would match expectations most accurately. |
Agreed, I think 2a is the clearest - maintains & semantics from general usage, but also interfaces with |
[Why is it that the second css-nesting comes into the picture there's a list with options and suboptions? :P] (2a) I'm not sure it's very consistent to disable the implied |
Yeah, 2b is semantically 'cleaner' in some ways (both selectors maintain their behavior), but I think this would be very surprising to authors, and not a meaningful way of supporting .media {
& > img { ... }
}
@scope (.media) {
& > img { ... }
} In the current spec, that works because we don't imply an initial |
That’s also the case with option 1, no? The way I read that option, is that inside So that this … : @scope (.media) {
& > img { ... }
} … equals that: @scope (.media) {
:scope {
& > img { ... }
}
} That would essentially make
🙈 |
Come to think of it: for |
I think in both css nesting and scope we want to think of it as an implicit descendant combinator, not an implicit extra level of nesting. |
The proposed resolution here is:
This builds on (and clarifies) the resolution in #7854 that |
Proposed resolution SGTM. Maybe we can also consider |
The CSS Working Group just discussed
The full IRC log of that discussion<fremy> miriam: the scope roots elements are currently part of the scope, with no implied relationship<fremy> miriam: so, if you use the same selector for both ends, the end matches the root <fremy> miriam: bramus and others found that confusing <fremy> miriam: so the proposal would be to imply that nesting scope selectors include :scope <fremy> miriam: except if they explicitly refererence :scope or use ampersand <fremy> miriam: there are a couple of differences between :scope and ampersand <TabAtkins> & references all the elements matched by the scope-start selector (as normal for Nesting), :scope matches the specific element that is functioning as the scope in a given element's context. <fantasai> +1 to the proposal <fremy> miriam: mainly you can use & multiple times <TabAtkins> +1 to the proposal <fremy> miriam: so the proposal clarifies the difference <astearns> ack fantasai <fremy> fantasai: what is the specificity of :scope and ampersand? <fremy> miriam: there is another issue on that <fremy> miriam: but my guess is that ampersand should work just as in nesting <fremy> miriam: (wrapping the starting scope selector in :is) <bramus> q+ <fremy> TabAtkins: (missed short comment) <fremy> astearns: does that work for you fantasai ? <astearns> ack bramus <fremy> fantasai: yes <TabAtkins> TabAtkins: That's also my preference <fremy> bramus: should we also introduce :end for the end boundary? <fremy> bramus: for sibling scopes, that might be useful <fantasai> proposal was to have & use the specificity of the selector it's referencing, and for :scope to have its normal specificity (1 pseudo-class) <fremy> miriam: this sounds like a separate resolution <fremy> miriam: could you provide some clear use cases for that? <TabAtkins> have we discussed the meaning of relative selectors like `> .foo`? Do those get captured by Nesting, implying an &, or do they imply a :scope? I think the latter should be the case. <fremy> astearns: the proposed resolution is in the last comment of the thread <fremy> astearns: looking at tab's question on irc <fremy> astearns: tab, do you want to voice the question? <fremy> miriam: I think I agree with TabAtkins suggestion <fremy> miriam: relative selectors (...missed) <fremy> miriam: question was what happens if the selector starts with a descendant combinator <fremy> miriam: so just adding a descendant combinator should be the same as the default <astearns> ack fantasai <fremy> fantasai: I think that it implies that every selector inside a scope that doesn't start with an ampersand has an additional pseudo-class specificity <fremy> TabAtkins: no, no difference <fremy> TabAtkins: the implied-ness is just for the meaning, but not the specificity <fremy> TabAtkins: the implied one does not add specificity <fremy> fantasai: p and :scope p are the same, but with different specificities <fremy> TabAtkins: yes <fremy> fantasai: and if I add (...) I could match more <fremy> TabAtkins: yes, not in that use case, but in others yes <fremy> fantasai: if you use descendants, you can match much more <fremy> fantasai: and both :scope and & can match the scoping element, but no other selector can <fremy> miriam: no other selector make it remove the nested-within combinator <fremy> TabAtkins: by the magic of relative selectors, it will never happen <fremy> TabAtkins: you have to make it absolute to override <fremy> fantasai: ok, this is probably fine, but the spec should be extra clear about it <fremy> astearns: so, the proposed resolution is to accept miriam's prososal + add new clarifications <fremy> astearns: any comment? <fremy> fantasai: lgtm <fremy> astearns: any objection? <fantasai> s/lgtm/I think this is a good change and I support it/ <fremy> RESOLVED: clarifications for scoping selectors proposed by miriam |
This was suggested by @bramus in an offline conversation.
In the current cascade-6 specification, the
@scope
rule defines a 'scope' as a tree fragment that includes the scope root (:scope
) element, but does not include any lower-boundary elements, or their decedents. Since the scope-root is 'in scope', it can be matched by scoped selectors:While it's possible to exclude the scope-root from selectors by appending
:not(:scope)
- we could consider doing it the other way around. For example, a 'shadow host' is not matched by selectors in the shadow DOM unless:host
is explicitly specified. The scope-root would still need to be 'available' to scoped selectors, but it would only match when specifically mentioned:On the one hand, it may be strange to have an element that is available 'in scope' but not matched by default. On the other hand, authors are likely to expect that matched elements will be 'nested' inside the scope-root selector. In either case, we would have a reasonable workaround for the counter-examples.
The text was updated successfully, but these errors were encountered: