Readit News logoReadit News
culi · 3 years ago
> Back in December, we wrote an article detailing three different options for CSS Nesting.

> Web developers responded to the poll with great clarity. Option 3 won in a landslide.

Yup, pretty much. The only thing I really wish won however was making the beginning "&" always required for nesting. Instead you're able to omit it if there's any other symbol. Example from article:

  main {
   .bar { ... }
   #baz { ...}
   :has(p) { ... }
   ::backdrop { ... }
   [lang|="zh"] { ... }
   \* { ... }
   + article { ... }
   > p { ... }
   ~ main { ... }
  }
The position of requiring & was not represented in the poll but seemed really popular in all the comments and seems like it would only make the parser's job easier (both now and in the future of CSS)

Regardless I'm just happy it's finally here! Hard to see the use-cases for sass in 2024 but, like jQuery, it's definitely made its mark on the history of the development of web standards

chrismorgan · 3 years ago
Relevant links on this:

https://twitter.com/LeaVerou/status/1580215877705687040, a poll about this specific matter (with links to other relevant polls which on the surface contradict this one).

https://github.com/w3c/csswg-drafts/issues/7834#issuecomment..., on this exact matter (chosen as a convenient starting point, after matters were already settled, but the whole issue is about it). By the time this poll was done, they had already decided not to consider mandatory-&, though I don’t really understand why (it’s pretty obvious to me that dividing into 3a and 3b would have been much more interesting than a couple of the other options which were straw men that no one was capable of taking seriously even if they tried).

https://github.com/w3c/csswg-drafts/issues/7961, about doing away with & in all cases for descendant selector (… which would be terrible for complexity and worst-case performance, and is only being considered because they already made things inconsistent by making & optional in every other case).

(I don’t like where it’s ended up, and consider requiring the & in all cases to be obviously materially superior, for both machine and human handling, and that there’s clear concrete advantage in having the requirement as an actual language rule rather than only a linter-enforced choice. People are far too hung up on exactly Sass syntax.)

> it would only make the parser's job easier

Mind you, it’s not a big difference; it’s just “if there’s no & in the selector, insert one and a descendant combinator at the start” in some shape, which could be as little as half a dozen lines of code net.

zestyping · 3 years ago
It's not a lot of code to implement, but it greatly simplifies usage by eliminating ambiguity:

- Easier for human readers (the "&" is an unmistakable visual indicator)

- Easier for human writers (fewer decisions; there's Only One Way To Do It)

- Easier for syntax colouring

rockwotj · 3 years ago
I remember the main argument against this is that you can always enforce this with a linter and either way it's not a slower parser, maybe slightly more complex.

Personally I do agree and I like the explicitness of always having the &

culi · 3 years ago
Yeah that's fair and I admit don't actually know anything about the parsing implications. I guess really I'm just looking for an excuse to convince my coworkers to adopt this practice without coming off like I'm bikeshedding haha
azangru · 3 years ago
> Hard to see the use-cases for sass in 2024

Possibly mixins, loops, and variables, which, unlike CSS variables, can be used in media queries.

ramesh31 · 3 years ago
>Possibly mixins, loops, and variables, which, unlike CSS variables, can be used in media queries.

Please god no. CSS is intended to be completely declarative. Loops and conditional logic were the very worst ideas SASS ever had.

clairity · 3 years ago
yes, mixins. even just static sets of declarations would be a great start, e.g., wanting to apply the same set of base rules to both an entity and various classes without error-prone repetition (which you typically separate to have control over cascading and specificity).

css variables in media queries would be helpful too, but mixins to me is the next big step after :has() (oh so useful, come on firefox!) and this nested css syntax. unfortunately, it may be years for us to see it in browsers. there's no consensus yet on mixin syntax or where in the css lifecycle it would be implemented (there are potentially serious performance implications apparently).

rkuykendall-com · 3 years ago
> Hard to see the use-cases for sass in 2024

Modules make writing CSS much less of a naming game. Anything you can do to reduce one of the 2 hardest problems in CS is worth it.

tipiirai · 3 years ago
Or build a design system with good names and take advantage of the global nature of standard CSS.
isleyaardvark · 3 years ago
> Web developers responded to the poll with great clarity. Option 3 won in a landslide.

Because there was no “none of the above” option, which developers asked for.

adamwathan · 3 years ago
One thing worth noting is that & substitutes for `:is(...)` in spirit under the hood, which means there are some significant behavior differences between native CSS nesting and Sass.

Here's one:

  .foo .bar {
    .baz & {
      color: red;
    }
  }

In Sass, that would compile to:

  .baz .foo .bar {
    color: red;
  }
With native nesting, it effectively compiles to:

  .baz :is(.foo .bar) {
    color: red;
  }
The Sass version matches this DOM structure:

  <div class="baz">
    <div class="foo">
      <div class="bar">
        ...
But the native version matches all of these structures:

  <div class="baz">
    <div class="foo">
      <div class="bar">
        ...
  
  <div class="foo">
    <div class="baz">
      <div class="bar">
        ...

  <div class="foo baz">
    <div class="bar">
      ...
Not a criticism at all (the `:is(...)` behavior is a very useful and welcome enhancement to CSS) but a notable difference worth understanding coming from Sass.

__ryan__ · 3 years ago
I’ll criticize it.

I recognize this is a preview and I desperately hope this implementation isn’t kept around and treated as a quirk.

This implementation is extremely unintuitive given their explanation of the expected behavior of CSS Nesting and the & symbol.

To quote:

    The & signals to the browser “this is where I want the selector from outside this nest to go”.
Their explanation and the actual implementation result in a majorly different CSS selector.

The implemented functionality, however useful, makes no sense as a default if one can explicitly use :is to achieve this behavior like below.

    .foo .bar {
        .baz :is(&) {
        }
    }
The default should behave like they claim it does; simply replace & with the “outside” selector.

jonny_eh · 3 years ago
With this hidden :is behavior, migrating to native CSS nesting from SASS will be extremely difficult.
TabAtkins · 3 years ago
Notably, this is identical to the behavior you get from @scope's nesting, and from passing a complex selector to an `el.querySelector()`.

(We discussed adopting Sass's behavior in <https://github.com/w3c/csswg-drafts/issues/8310#issuecomment...> but ultimately dropped it.)

DrBenCarson · 3 years ago
Agree important to note the difference but I personally prefer the nested CSS behavior. Much more sensible to use `&` as a logical operator
c-smile · 3 years ago
Nested rules is just a syntax sugar.

In Sciter, 10 years ago, I came up with style sets:

    @set Main {
      :root { ... } // root element that has this set applied 
      .bar { ... } 
      article { ... } 
      :root > article { ... } 
    }

    main { style-set: Main; } // main element with the set applied 
This solution solves two problems:

1. Modular/componentized style definition - same goal as in nesting styles, but without introduction of new syntax constructs.

2. Reduces CSS resolution load. Rules inside the set are scanned only for DOM children that have style set defined.

3. DOM element may have @styleset="url#name" attribute defined - used in components (Web alike components and React alike components)

ocimbote · 3 years ago
If syntactic sugar was really just sugar, JS would have sticked to callback functions, and we’d still be inventing abstractions to make our lives easier.

Syntactic sugar, sometimes, is the promise of sunnier mornings and that matters.

scambier · 3 years ago
"For a Linux user, you can already build such a system yourself quite trivially by getting an FTP account, mounting it locally with curlftpfs, and then using SVN or CVS on the mounted filesystem. From Windows or Mac, this FTP account could be accessed through built-in software."
c-smile · 3 years ago
Well, that's the matter of live systems design.

When you want to add a feature you should ask first if that can be accomplished by existing mechanisms.

And the second, if to go with with the change that affect millions of users, can we solve not just one problem (that already has a solution like LeSS & Co.) but possibly other principal too?

So for #1. If we already have @media sections, why not to use the same notation?

   @media name { ...rules... }
and

   @set name { ...rules... } 
@set can use existing code in parsers. Not just in browsers but in tons of existing tools and editors that do syntax highlighting.

And #2. Style sets solve problem of global CSS namespace pollution.

Consider this rule:

   div [name="some"] { ... }
then, while calculating styles of DOM elements, absolutely all N DOM elements need to be checked against this rule. So it is a O(N) complex task. And proposed nested rules thing does not reduce the N, but may make this even worse - more rules will be used.

While in style set solution:

   @set ComponentA {
      div [name="some"] { ... }
   } 
that rule will be checked only against children of componentA - the rule is local/scoped to DOM subtree. Still O(n), but n <<< N.

bryanrasmussen · 3 years ago
unpopular opinion I'm sure from reading everyone here, but to me nesting css is syntactic poison - or maybe syntactic sucrose or something that gives you cancer you use too much of it?

Anyway programmers given nesting just do it all the time which ends up leading to stuff like

article.news section.preamble h1 and probably a few other selectors after that all nested giving you a wonderful high priority for your style and possible collisions.

Then the same guys who made the problem can't figure out the problem so they figure some highlevel nesting is the solution so there won't be any collisions and overriding of styles.

LoganDark · 3 years ago
> Nested rules is just a syntax sugar.

But this syntax can also be used in minified CSS. I'm sure minifiers will have a fun time with this in 5 years when most of the major browsers support it.

I've seen all sorts of examples of stylesheets that would benefit from this, Tailwind Typography being a good one because it styles all sorts of nested elements but only inside of `.prose`. Eliminating tens or hundreds of `.prose` selectors by wrapping them all in a single `.prose { }` would make it smaller; not sure exactly how much smaller though.

This sounds like a fun case study.

cphoover · 3 years ago
Maybe I am an outlier... but I really don't like nested style documents like those founds with SASS, LESS, PostCSS. When the number of nested selectors becomes too great it can become very difficult to reason about. I would never use this without some kind of lint rule enforcing a maximum depth of selector nesting. I agree with the other commenters ITT taking the position flat CSS looks cleaner than nested documents.
rezonant · 3 years ago
The difficulty you mention is definitely an issue, but the insane repetition required for even a modestly complex piece of UI when using "flat" CSS is worse, in my opinion. I suppose there might even be a slight efficiency gain over the wire once Sass outputs nested CSS by default.
pier25 · 3 years ago
I wrote flat CSS for many years and yeah it's a lot of work but also I find it becomes more difficult to parse visually.

Like when writing HTML or regular code, I find indentation helps me parse and navigate the structure very easily.

There are cases with complex components where it can become a bit complex, but it's trivial to split the tree in multiple parts to reduce the indentation.

jakelazaroff · 3 years ago
I agree: even when I use preprocessors, I rarely nest “normal” selectors. The real win is nesting pseudoselectors (:hover, :focus, etc) and media queries.
AltruisticGapHN · 3 years ago
You should use stylelint anyway and then you can set `max-nesting-depth`

https://stylelint.io/user-guide/rules/max-nesting-depth/

I mean, these days almost every JS developer use some kind of linter - why would you not use a linter for CSS? Literally nothing to lose since you can set the rules as relaxed as you want.

PS: I set it to 3 - Using good convention like SuitCSS I have never found I needed more nesting. Usually you think about a problem and find a simpler way to do it.

https://github.com/suitcss/suit/blob/master/doc/naming-conve...

TLDR If you use any of the good practices for CSS such as BEM or BEM-like you don't have lots of nesting anyway.

And I like how the article mentions as an example `ul article ul` and how to solve it by adding a symbol :is() to be able to nest, and it's literally the one thing you don't want to do anyway, which is a selector like `ul article ul` (as per BEM methodology). Instead `.list .article .article-list` as a veyr poor example doesn´t need the special "fix" the article mentions.

frereubu · 3 years ago
I generally only nest one level down, and at most two. Any more and, as you say, it becomes very convoluted, particularly when it comes to specificity. However, alongside pseudo elements, the killer feature for me is that nesting enables namespacing for components, which (a) leads to much simpler class names that makes CSS much easier to read and (b) stops a great deal of repetition of the class on the wrapper element.
JimDabell · 3 years ago
> When the number of nested selectors becomes too great it can become very difficult to reason about.

This is a sign you need to decompose whatever design you are working on into smaller components. If you’re trying to write styles for a whole page at once, you’ll see this problem, but if you are working on small components, it’s very rare.

esperent · 3 years ago
> decompose whatever design you are working on into smaller components

I haven't followed modern CSS development much. Does it have a module system now?

65 · 3 years ago
If you give a junior front end developer CSS nesting, you can get some very janky results.

Working with SCSS codebases and junior developers, I've seen SCSS nesting get so bad, the line order of the selector in the stylesheet would determine what styling gets used.

Nesting CSS is useful in some cases, but for the majority of use cases it can get unwieldy very quickly.

onion2k · 3 years ago
When the number of nested selectors becomes too great it can become very difficult to reason about.

When any complexity becomes too much it makes it harder to reason about. The solution is to avoid complexity; you can do that while using a small number of nested selectors.

toastal · 3 years ago
It’s Sass & Less, not SASS & LESS. Less is sometimes stylized with all caps (or all lower like {less}) and is an acronym for Leaner Style Sheets, but Sass was never was stylized with all caps nor is it an acronym.
SamEdosa · 3 years ago
This is great! The only reason I use SCSS is for the nesting. It should have been implemented 10 years ago, but better late then never.
dgb23 · 3 years ago
It's great that parts of SCSS are getting superseded by CSS.

Nesting is great to avoid selector repetition.

Custom properties (CSS variables) and CSS functions give us tools to avoid magic numbers and to encode layout relationships.

New sets of selectors and container queries let us decouple and re-use declarations more.

CSS Houdini gives us further power in extending CSS functionality.

Of course there are things that SCSS provides which are unlikely in the scope of future CSS proposals such as datastructures (maps) and loops to generate classes and mixins. But I can already imagine a world were those aren't necessary anymore for many cases.

brewdawg · 3 years ago
> SCSS are getting superseded by CSS.

Reminds me of how Coffeescript died out because its best ideas got integrated into Javascript.

What I want to know is: how the hell did this take so long? Nesting is such an obviously useful feature to have in CSS, and once I'd experienced it in SASS I never wanted to be without it. Why did it take 10+ years for this to be introduced to CSS, especially when other browser-based technologies like JS have evolved enormously in that time?

amjnsx · 3 years ago
For me this is where something like PostCSS shines. You simply write future css and remove the plugin when it’s supported natively.

This wins in my opinion because there shouldn’t be any conversion necessary from something like Sass to CSS

tehbeard · 3 years ago
What's the hit/miss rate on that CSS changing syntax?

I Vaguely recall something similar happening with decorator syntax/how it worked in JS/typescript.

Or do you keep to CSS features that are locked down in terms of spec, just waiting on implementation to roll out?

a1371 · 3 years ago
Awesome to finally have nesting. The way I see it, this took 10 years longer than it should have.

I feel the only big thing missing from the vanilla stack for me right now is a template element that multiple html files can share. Just like how you make a blog header in Jekyll or Hugo and it adds it on all your blog posts get the header. I haven't found an easy way of doing that if I have a bunch of html pages.

alxmng · 3 years ago
That's what an iframe is? I guess there could be a partial element that works like <partial href="header.html" /> but if it's referencing HTML, what about JavaScript or CSS it includes? That's exactly what iframe handles.
robgibbons · 3 years ago
What you're asking for is called Server-Side Includes, it's been a feature of Apache for ages, but is also supported by Nginx and other servers.
miragecraft · 3 years ago
We had it briefly in the form of HTML imports, but the powers that be removed it because it’s not powerful enough for JavaScript/web apps development; totally ignoring the fact that the web isn’t just about apps.
nightpool · 3 years ago
well, the classic solution has always been to use an iframe :p
a1371 · 3 years ago
I don't know if that's actually an ok method or not, but I thought of that and looked around for it with little luck
jefftk · 3 years ago
Not implemented in Firefox yet, but they like it: https://github.com/mozilla/standards-positions/issues/695

They're tracking work in https://bugzilla.mozilla.org/show_bug.cgi?id=1648037

frosted-flakes · 3 years ago
Will nested CSS support mixing properties and nested rules in any order, or do all the nested rules have to grouped together at the end? Right now, I frequently write SCSS rules like this:

  .some-class {
      background: blue;
      &:hover {background: red}
      border: 1px solid;
      &:active {border: 1px dashed}
      padding: 16px;

      display: flex;
      gap: 8px;
      
      & > * {
          color: red;
      }
  }
And it would be a pity if that wasn't allowed.

The reason I ask is because I seem to remember an early proposal not allowing this, but I can't find where I read it.

mtber · 3 years ago
As I understand it, you can mix it but the parser will hoist all the immediate some-class styles to the top
culi · 3 years ago
Why would it not support it?
frosted-flakes · 3 years ago
I don't know, that's why I'm asking.