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-nesting-1] Name, terminology, and nesting selector misnomers are footguns (solution proposed) #8329
Comments
After some further reading, I see the scoping concept is being updated as part of css-cascade-6, and even has issue 11 for determining the interaction with css-nesting-1. Based on the direction of that, I more strongly believe "nesting" is not a useful term for the unique behaviour of this spec, especially when multiple at-rule blocks already allow nesting that will likely intermix with this one. The newer expanded use of |
I made a similar point during the WebKit vote last month, arguing to change the name to "Selector Inheritance" instead. However, my suggestion for doing so was mainly to decouple the behavior from the syntax, back when everyone assumed the behavior would be like SCSS Nesting. I was also worried that the term "nesting" would wrongfully entail scoping of styles, which the WebKit explainer did not suggest. However, now that the spec has agreed to use the nesting syntax and plans to scope nested styles to the selected elements of the parent selector, this feature is unmistakably "CSS Nesting". It just doesn't mean the same thing as "SCSS Nesting" because SCSS uses improper terminology and should have likely called their feature "Selector Inheritance". That being said, since we're no longer getting SCSS-like nesting behavior, I agree that using And while we're suggesting syntax changes again, if we want to preserve cross-compatibility with SCSS nesting, I also still think the Option 4 syntax was best. All things considered, I think CSS Nesting should look like this: .a .b {
// parent selector styles ...
} {
.c :scope {
// nested styles ...
}
.d {
// nested styles ...
}
} Then in SCSS Nesting, although it's ugly, you can take advantage of both features: .a .b {
// parent selector styles ...
.d {
// nested styles ...
}
} {
.c :scope {
// nested styles ...
}
} |
It is not safe to reuse This conversation has come up several times, because there clearly is overlap in use-cases between nesting and scope - but every time it's discussed, we find that they cannot simply be merged. The use-cases overlap, but are not identical. It's important that they work together, but that requires keeping the syntaxes distinct. Nesting is likely to happen in and around scoped rules, and the distinct meanings need to remain clear even when combined. |
Except nesting is already a syntax and terminology that exists in CSS, yet has no single behaviour attached to it. Naming this "nesting" would be defining behaviour for only one usage of nesting purely because it uses that syntax, while creating confusion where other specs use the same term and syntax already (on top of that from familiarity with the "Selector Inheritance" behaviour).
It would be safe to use for this purpose, as it still doesn't need redefining from selectors-4, and css-cascade-6's scoping mechanism already supports and allow most of what is needed. The most significant change I foresee is that What happens if I put It would need to explicitly show that These are not foreign concepts to either spec.
I'm saying it already acts like one, so it probably should be defined in the shared language of one, so why is this not a route to take?
Can you point to something to support them not being mergeable and/or the syntaxes having to be distinct? The only conflict I see is deciding if the scoping proximity rules fit the use-cases covered by css-nesting-1 (which I think they do), and if it's decided to use strong proximity for scoped descendants by default (latest draft suggests it won't), does that remain the case, and if not, how to modify the behaviour (which may require a distinct syntax, or something that works across them all). |
This syntax defines how style rules are nested into other style rules; calling the spec "Nesting" works just fine, and there's not really anything that it's ambiguous with.
It matches one of the scoping elements from the nearest
It matches one of the scoping elements from the nearest
Indeed they're not, This is probably a minor loss, all in all (and you can't refer to grandparent nesting rules in Nesting, anyway), but a
Nesting does not act like a scoping container. It's very much normal to write nested rules that aren't remotely scoped to the outer rule, like |
Except it's not really a style rule inside a style rule, is it? It's a shorthand for an at-rule, and the nesting this is defining doesn't apply to other specs using their version of nesting. It's a conflict to call them all nesting while defining only one of them as nesting that works in a unique way.
But with
Why would you need to use them together in that way? If the use of each is creating a new scope, you would just write and nest your selectors and scopes accordingly. Unless I'm misunderstanding, as it currently stands, your example would be
Except if nesting was scoping, they have the same semantic meaning. I'd also argue being meaningful is both situational and not the important factor for referring to it later, as a unique scope is less likely to be reused than one that could match multiple times as in nesting (i.e. the same scope matching inside that scope).
How is that not scoped? A limited scope should not be seen as the only way to use I said scoping limits (a behaviour not part of
|
I have no idea what you mean. Only
Yes, :scope allowed anywhere. I'm not sure what point you're making here, tho.
Why wouldn't you? It's a perfectly reasonable selector.
Right, but what I'm saying is they don't have the same semantic meaning, so nesting isn't scoping. The different semantics correspond to different behaviors and different use-cases. Trying to collapse them loses a lot of valuable stuff.
Scoping has a meaning. |
It's
That it being allowed anywhere and everywhere would be needed for "nesting" and is generally limiting if not allowed. If it already is as you say, it's not being indicated in that spec right now. That it seems to enforce root + descendants only for scopes (hard to really be sure, it's implied throughout, but only gets touched upon under the scoped descendant combinator), my reading is that Impractical examples: @scope (.inner) {
.outer :scope.special {...}
} Would be scope @scope (.inner) {
@scope (.outer :scope.special) {
...
}
} Would be outer scope (Whether or not the parent mechanism should modify the meaning of
Not sure I'd call that a "perfectly reasonable" selector, and certainly that's why I see now how I read it wrong. There's obviously better ways to write it in the first place, and I still don't see anywhere in the spec that allows it to mean anything but scope
I will concede I have not read most of selectors-4 in several years, and I see the language was updated to not allow anything but the former scope-filtered meaning since 2018. It used to have more permissive meanings and scope-relative allowed the meaning I'm giving here, so I guess I'm making an argument for that being allowed again. |
No, that was an earlier version of the spec. There is no at-rule anymore in the current spec.
The
It turned out that we didn't actually want the "scope-relative" meaning anywhere. |
It may not exist anymore, but I guess I will always implicitly see the short-hand version is really that.
Thanks, I understand what you're saying now. I still think that needs explaining more far more clearly in the spec, especially with examples of I do remain unclear about multiple uses of
Not sure what you mean here? Both allow referring to elements outside the scope, but match to an element outside the scope in what
I don't see the no relation (including your I still think it's wrong to call this spec nesting while other specs use the term with a more general meaning that doesn't need defining (clearly showing css-nesting-1 is the odd one out here). Yes the rules are nested, it's more direct than others due to not needing selectors in the body to achieve it, and the spec leads with those things, but there's then the other at-rules that lead to nesting of rules without having relevance to the nesting of this spec. The rest of it is not specifically about the nesting, but about a way of creating a context for relative selectors that allows this type of nesting to work. That last part should be the focus and source of the naming. |
Closing this issue; ultimately the only remaining disagreement is about the shortname, and the CSSWG is happy with the css-nesting shortname. |
Problem
From #8310, I'm convinced this spec is currently a big footgun, due to the similarity to preprocessor nesting, and much of the feedback and expectations of it come from believing it can replace most use cases for preprocessor nesting, most notably as sugar for combining multiple selectors to avoid duplication.
As per that issue, it can not achieve this currently, and if it was changed to be able to, it would be a difficult enough challenge for implementers to make it performant, that they would have to delay it indefinitely until that difficultly can be overcome.
Assuming the current behaviour described (
:is()
is implicit on&
, so that&
refers to the parent selector's selected elements, not the parent selector) remains as is, I think this spec is going to (continue to) elicit a great deal of misunderstanding, with extra difficultly troubleshooting (by way of implicit forgiving selectors), and requiring a lot of learning resources to clarify things and list the many "gotchas" authors can encounter. It will also have to continue coexisting with the preprocessors tools, which right now seems problematic with it sharing much of the same terminology and syntax.Proposed Solution
To avoid all this (while allowing for a future where preprocessor-style nesting may still be introduced to CSS), I'd like to propose changing the name, terminology, and nesting selector.
Change Naming & Terminology
I believe "nesting" is a misnomer for this spec's original intent and current state. Nesting is just a by-product of the syntax chosen and existing syntax for writing rules, there's no (to my knowledge) inheritance between the nesting happening so there's no hierarchal nesting, and it's obviously not manipulating ascendant and descendant context selectors, so referring to it by an inconsequential aspect of it seems misleading.
I think it would be more fitting to be referred to as "chaining" or "scoping". What the spec achieves could be better described as chaining the results (i.e. selected elements) of distinct selectors, to create arbitrary scopes within that chain for applying new rules. Making that clearer in name and terminology will help differentiate it, and avoid many of the misunderstandings and "gotchas" for authors.
I'm aware "chaining" is already sometimes used as a misnomer for the descendant combinator, but I think correcting that would be a bonus. I'm also aware [css-scoping] exists, but as I understand the current state of that spec,
@scope
is not used, and the name "scoping" doesn't quite fit it when it's not utilising:scope
, defining scope as a concept and only focuses on the scoping/encapsulating for the shadow DOM. If there is conflict with [css-scoping], it would probably be a good time to look at the shared concepts and behaviours that could be resolved together.Change Nesting Selector
With the above in mind, I believe
:scope
should be used instead of&
, because::scope
has an existing understanding of referring to the already selected elements when used in new selector within that scope:scope
will make it clear that the nested parent's selector will already be resolved to selected elements, therefore nesting is more like chaining selectors in a similar way as JS does, and not sugar for deduplicating multiple selectors:scope
is underutilised (being limited to CSS queries in JS), so prime real-estate for expanding upon (e.g.,Element.querySelector('div :scope')
and similar would also become possible under the same logic as a chaining selector that establishes a new scope.)&
reads too much like an "and" combinator, which would be a new and unnatural concept in CSS&
already has an understanding in preprocessor toolsClosing
I think these changes largely shrink the footgun potential, by differentiating it from preprocessor nesting almost entirely, and making the behaviour more explicit and intuitive for it's unique place in CSS. I would feel far more comfortable about the short and long term impact of the existing behaviour being used if that happened.
(Apologies if some of these topics have been covered in depth before, I've been away from web development for years, and from some searching of open and closed issues, I only found issues mentioning some of these things in different contexts, but not this same issue and proposal)
The text was updated successfully, but these errors were encountered: