3 ms·
These all feel like an overengineered solution in search of a problem, with some degree of tunnel vision in that all three proposals try to support the same bro
by krajzeg 4y ago
These all feel like an overengineered solution in search of a problem, with some degree of tunnel vision in that all three proposals try to support the same broad set of capabilities.
It looks like somebody decided that nesting support must somehow support "reverse nesting", eg. that you'd like to define what happens to .foo when it's inside a .bar, but nested inside the definition for .foo:
.foo {
.bar > .foo {
...
}
}
Does anybody actually want this? It feels counter-intuitive and weird, and with the syntaxes proposed, seems to provides little benefit compared to just doing it as the old ".bar > .foo" without nesting.
If you drop the requirement for nesting to work in reverse, you can just go with the proven SCSS syntax which is extremely clear, straightforward to use, and requires 0 extra characters typed.
EDIT: Apparently the '&' or some other special token is required to prevent the need for unlimited lookahead while parsing. This is actually explained behind a folded caption in the article, which I initially missed.
- akdor1154 4y agoThe @media application of this seems useful, but yeah arbitrary parents seems not a must-have.
- krajzeg 4y agoApparently, those already work differently than other selectors in the proposals (example 7): .foo { display: grid; @media (width => 30em) { grid-auto-flow: column; } } I would expect "@nest @media (width => 30em) & {" for consistency with how it works everywhere else, but apparently @media is already special anyway in the "@nest" proposal. I agree that this syntax could be convenient, though I'm actually a fan of having all the "@media" changes in one place, which is what the current syntax forces.
- somishere 4y agoApologies if I misunderstand, but your "reverse nesting" syntax already works with scss. I.e. `.a{ .b & {}}` => `.b .a {}` ... I'd quite honestly use it fairly often, usually with state/data modifiers on an ancestor (or ancestor sibling!)
- krajzeg 4y agoPerhaps it was my own CSS preferences speaking, where I try to limit "spooky action at a distance" for consistency. But yeah, a".selected" state on an ancestor seems like a good use-case for this if you have different tastes. I stand corrected and see how that's useful. I assume that for the same reason that they cannot support direct nesting with no extra tokens (parsing issues), they also cannot support the simple SCSS version and instead went for the "@nest .b & {" mouthful.
- somishere 4y agoIt's a mouthful alright!
- deleted 4y ago[deleted]
- dieulot 4y agoLooks useful to me in order to accommodate parent modifiers classes. .button { @nest div.small-print & { a { @nest :not(nav) & { Including the body: .button { @nest body.has-js & {
- eurasiantiger 4y agoThis is a flawed approach and leads to N:M combinatorial explosion in stylesheets. Sure, it’s convenient to have component styles react to the context they’re in, but CSS Custom Properties are a much better solution for that.
- chrismorgan 4y ago> a { @nest :not(nav) & { FYI, this `:not(nav) a` doesn’t do what you almost certainly intended. It doesn’t match “an <a> that is not inside a <nav>”, but rather “an <a> that has at least one ancestor that is not a <nav>”. You can’t currently express what you wanted there; the best you can generally manage is if you can anchor it with a parent selector, e.g. `:not(nav) > a`, which will match any <a> whose immediate parent is not a <nav>. I can imagine something along the lines of `a:not(:has(nav :scope))` working in the future too.
- emn13 4y agoTo play devil's advocate: there's a case to be made that reverse nesting is precisely the the _most reasaonable_ case for nesting, and that forward nesting is the one to be avoided. The problem with nesting is that it is seductively easy to write, but encourages two coding issues that cause maintenance headaches later on. Firstly, it encourages high selector specificity, and that means potentially enjoying specificity battles later on. Secondly, it encourages tightly coupled DOM structure with CSS - and tight coupling makes later development more expensive. Both of these issues are significantly less serious when using reverse nesting than forward nesting. Forward nesting allows for expressing the concept of "parts of a component" by it's DOM structure, so when the component is tweaked, selectors that aren't explicitly tied to any part of a component suddenly break. But reverse nesting is more natural to use in the context of expressing a special case; i.e. my thingmabob is generally green, but in this specific context it's grey. So on coupling, reverse nesting is less risky: whil it's not impossible to "compress" your css and thus introduce coupling between component structure and a reverse nested selector, it's not a very natural mistake to make. And on specificity too, reverse nesting is less likely to cause surprises - after all, since you're expressing a more specific situation, you're almost always likely to want the nested selector to win that specificity battle. So, I'd argue that reverse-nested selectors are actually one of the few general class of nested CSS selectors that are unlikely to cause maintenance headaches later on. Similarly harmless are nested media selectors (again, because nesting implies expressing an exception), and nested pseudo-elements (because there structure and CSS are intrinsically coupled an expressed within the CSS anyhow). What you call "reverse nesting" is actually the only best good kind of nesting. QED?
- LocalPCGuy 4y agoJust piping up to say yes, absolutely want the ability to put the `&` anywhere. Your example isn't exactly correct, what I use it for is adjusting styles of the element I'm referring to based on a parent class. The `&` isn't automatically prepended - it puts the element reference in the spot it sits in the CSS. In your example, the `.bar` would be the parent class that is adjusting the styles of the current element. For: `@nest .bar > & { ... } }` (just using the first syntax for simplicity here) That doesn't translate to: `.foo { .bar > .foo { ... } }` It's actually just: `.bar > .foo { ... } }`