[css-nesting] request to pick up the css-nesting proposal #2701

Closed
jonathantneal opened this Issue May 24, 2018 · 62 comments

Comments

Projects
None yet
@jonathantneal
Contributor

jonathantneal commented May 24, 2018

https://tabatkins.github.io/specs/css-nesting/

The CSS Nesting module introduces the ability to nest one style rule inside another, with the selector of the child rule relative to the selector of the parent rule. This increases the modularity and maintainability of CSS stylesheets.

This is a followup to #998, and a long-time request from developers.

Has this been discussed in an agenda yet? If not, could this please be added to a future agenda?

Tweets lifted from @chriscoyier, @LeaVerou, @auchenberg, and @SaraSoueidan. Specification by @tabatkins.

@jescalan

This comment has been minimized.

Show comment
Hide comment
@jescalan

jescalan May 24, 2018

Couldn't be more in favor of this. Every developer uses css nesting and has forever through sass/less/stylus/postcss/etc, and it seems like the spec is in a solid place. Not having to pre-compile nesting anymore would be fantastic.

Couldn't be more in favor of this. Every developer uses css nesting and has forever through sass/less/stylus/postcss/etc, and it seems like the spec is in a solid place. Not having to pre-compile nesting anymore would be fantastic.

@LeaVerou

This comment has been minimized.

Show comment
Hide comment
@LeaVerou

LeaVerou May 25, 2018

Contributor

Yes please.

I wonder if this could also solve developers' requests for scoping. Two birds with one stone. I.e. instead of having nesting as merely syntactic sugar for the equivalent selectors, making it an alternative to preprocessors, make these rules have higher priority than non-scoped rules.

To clarify with an example, given the following CSS:

#foo p { color: red }

.bar {
  & p { color: green }
}

and the following HTML:

<div id="foo">
  <div class="bar">
    <p>foo</p>
  </div>
</div>

The paragraph would be green.

I know that we are dead set against introducing any new specificity rules, but it seems that scoping is such a huge problem that developers are avoiding the cascade altogether (see also CSS in JS which apparently half of devs use now?), We need to give them tools to avoid these problems, and it doesn't look like minor changes will do it. @tabatkins seemed to understand the problem well in a series of recent tweets, perhaps he can elaborate here too.

Contributor

LeaVerou commented May 25, 2018

Yes please.

I wonder if this could also solve developers' requests for scoping. Two birds with one stone. I.e. instead of having nesting as merely syntactic sugar for the equivalent selectors, making it an alternative to preprocessors, make these rules have higher priority than non-scoped rules.

To clarify with an example, given the following CSS:

#foo p { color: red }

.bar {
  & p { color: green }
}

and the following HTML:

<div id="foo">
  <div class="bar">
    <p>foo</p>
  </div>
</div>

The paragraph would be green.

I know that we are dead set against introducing any new specificity rules, but it seems that scoping is such a huge problem that developers are avoiding the cascade altogether (see also CSS in JS which apparently half of devs use now?), We need to give them tools to avoid these problems, and it doesn't look like minor changes will do it. @tabatkins seemed to understand the problem well in a series of recent tweets, perhaps he can elaborate here too.

@fantasai

This comment has been minimized.

Show comment
Hide comment
@fantasai

fantasai May 25, 2018

Contributor

@LeaVerou See https://www.w3.org/TR/2014/WD-css-scoping-1-20140403/#scope-atrule ? I think if it's affecting the cascade in such a way, it should be more explicit. Nesting has traditionally been just syntactic sugar.

Contributor

fantasai commented May 25, 2018

@LeaVerou See https://www.w3.org/TR/2014/WD-css-scoping-1-20140403/#scope-atrule ? I think if it's affecting the cascade in such a way, it should be more explicit. Nesting has traditionally been just syntactic sugar.

@bradkemper

This comment has been minimized.

Show comment
Hide comment
@bradkemper

bradkemper May 25, 2018

+1 on nesting, and also +1 on being explicit with an @scope.

For Lea’s example, I would be surprised if the specificity was not equivalent to .bar p.

+1 on nesting, and also +1 on being explicit with an @scope.

For Lea’s example, I would be surprised if the specificity was not equivalent to .bar p.

@thescientist13 thescientist13 referenced this issue in ProjectEvergreen/project-evergreen May 25, 2018

Open

Add support for nested selectors #23

@LeaVerou

This comment has been minimized.

Show comment
Hide comment
@LeaVerou

LeaVerou May 26, 2018

Contributor

Agreed, haven't seen the @scope rule!

Contributor

LeaVerou commented May 26, 2018

Agreed, haven't seen the @scope rule!

@anjia

This comment has been minimized.

Show comment
Hide comment
@anjia

anjia May 29, 2018

Clap clap. Look forward to using css-nesting in browsers directly without any pre-compiling.

Even though css-nesting looks like a syntactic sugar, it means the enhancement of coding efficiency and code maintainability for CSS, you know, which is what developers are gladly pursuing for. And sometimes, writing style could affect people's thinking processes.

And @scope is also a very useful feature, it could allow authors to use short classnames and selectors without worrying about unexpected cascading, or styles interaction among different UI components on the same page.

anjia commented May 29, 2018

Clap clap. Look forward to using css-nesting in browsers directly without any pre-compiling.

Even though css-nesting looks like a syntactic sugar, it means the enhancement of coding efficiency and code maintainability for CSS, you know, which is what developers are gladly pursuing for. And sometimes, writing style could affect people's thinking processes.

And @scope is also a very useful feature, it could allow authors to use short classnames and selectors without worrying about unexpected cascading, or styles interaction among different UI components on the same page.

@fantasai

This comment has been minimized.

Show comment
Hide comment
@fantasai

fantasai May 29, 2018

Contributor

@scope isn't syntactic sugar though. It adds another dimension to the cascade, more significant than specificity but less significant than origin/importance. See https://www.w3.org/TR/2016/CR-css-cascade-3-20160519/#cascading which defines how scoping affects the cascade.

Contributor

fantasai commented May 29, 2018

@scope isn't syntactic sugar though. It adds another dimension to the cascade, more significant than specificity but less significant than origin/importance. See https://www.w3.org/TR/2016/CR-css-cascade-3-20160519/#cascading which defines how scoping affects the cascade.

@anjia

This comment has been minimized.

Show comment
Hide comment
@anjia

anjia May 30, 2018

Even though it seems like just a syntactic sugar, it means the enhancement of ...

Oh, the pronoun it above refers to nesting. Eh, it's really easy to result in ambiguity, I'm going to update my comment to clarify this.

@fantasai thanks for your details and relevant link :)

anjia commented May 30, 2018

Even though it seems like just a syntactic sugar, it means the enhancement of ...

Oh, the pronoun it above refers to nesting. Eh, it's really easy to result in ambiguity, I'm going to update my comment to clarify this.

@fantasai thanks for your details and relevant link :)

@tobireif

This comment has been minimized.

Show comment
Hide comment
@tobireif

tobireif May 31, 2018

Please also see the existing ticket #998 .

Please also see the existing ticket #998 .

@tobireif

This comment has been minimized.

Show comment
Hide comment
@tobireif

tobireif May 31, 2018

I also want nesting, it'd be a useful feature.

Regarding https://tabatkins.github.io/specs/css-nesting/ :

I'd prefer a syntax like that of Sass

https://sass-lang.com/guide#topic-3

where it's not necessary to add the ampersand.

In Sass, the ampersand is available (but not required - that's what I want).

https://sass-lang.com/documentation/file.SASS_REFERENCE.html#parent-selector

One of their examples:
(plus my comments)

#main {
  color: black;
  /* ampersand not required: */
  a {
    font-weight: bold;
    /* ampersand can be used when necessary: */
    &:hover { color: red; }
  }
}

is equivalent to this:
(the second part of their example) (their formatting)

#main {
  color: black; }
  #main a {
    font-weight: bold; }
    #main a:hover {
      color: red; }

I also want nesting, it'd be a useful feature.

Regarding https://tabatkins.github.io/specs/css-nesting/ :

I'd prefer a syntax like that of Sass

https://sass-lang.com/guide#topic-3

where it's not necessary to add the ampersand.

In Sass, the ampersand is available (but not required - that's what I want).

https://sass-lang.com/documentation/file.SASS_REFERENCE.html#parent-selector

One of their examples:
(plus my comments)

#main {
  color: black;
  /* ampersand not required: */
  a {
    font-weight: bold;
    /* ampersand can be used when necessary: */
    &:hover { color: red; }
  }
}

is equivalent to this:
(the second part of their example) (their formatting)

#main {
  color: black; }
  #main a {
    font-weight: bold; }
    #main a:hover {
      color: red; }
@tabatkins

This comment has been minimized.

Show comment
Hide comment
@tabatkins

tabatkins May 31, 2018

Member

My spec explains why that's not a viable possibility. (Browsers don't want unbounded lookahead in their CSS parsers.)

It also privileges the descendant combinator, which isn't ideal.

Member

tabatkins commented May 31, 2018

My spec explains why that's not a viable possibility. (Browsers don't want unbounded lookahead in their CSS parsers.)

It also privileges the descendant combinator, which isn't ideal.

@tobireif

This comment has been minimized.

Show comment
Hide comment
@tobireif

tobireif Jun 1, 2018

that's not a viable possibility.

If I understand you correctly it is a viable/possible option but it would require unbounded lookahead in CSS parsers.

From your draft:

"this drawback is generally considered unacceptable among popular implementations of CSS."

Are there sources for this?

Is it a performance issue?

It also privileges the descendant combinator, which isn't ideal.

Can you elaborate? Thanks in advance!

As for most feature wishes: The main objective (speaking for myself) is to get the feature, the rest is just details.

I'd strongly prefer not being required to prepend an ampersand to every single nested rule, and I hope that spec writers and implementers find a way to avoid that (perhaps it could be prototyped and tested and perhaps the perf impact is not really noticeable), but I'll sure take the feature even with that tedious requirement.

tobireif commented Jun 1, 2018

that's not a viable possibility.

If I understand you correctly it is a viable/possible option but it would require unbounded lookahead in CSS parsers.

From your draft:

"this drawback is generally considered unacceptable among popular implementations of CSS."

Are there sources for this?

Is it a performance issue?

It also privileges the descendant combinator, which isn't ideal.

Can you elaborate? Thanks in advance!

As for most feature wishes: The main objective (speaking for myself) is to get the feature, the rest is just details.

I'd strongly prefer not being required to prepend an ampersand to every single nested rule, and I hope that spec writers and implementers find a way to avoid that (perhaps it could be prototyped and tested and perhaps the perf impact is not really noticeable), but I'll sure take the feature even with that tedious requirement.

@tabatkins

This comment has been minimized.

Show comment
Hide comment
@tabatkins

tabatkins Jun 1, 2018

Member

Are there sources for this?

The sources are that this group is full of browser developers, and they've expressed that exact sentiment.

Is it a performance issue?

Potentially, but it also just rules out certain nice classes of parsers. Bounded lookahead is very convenient and has well-known performance characteristics.

Member

tabatkins commented Jun 1, 2018

Are there sources for this?

The sources are that this group is full of browser developers, and they've expressed that exact sentiment.

Is it a performance issue?

Potentially, but it also just rules out certain nice classes of parsers. Bounded lookahead is very convenient and has well-known performance characteristics.

@tobireif

This comment has been minimized.

Show comment
Hide comment
@tobireif

tobireif Jun 1, 2018

it also just rules out certain nice classes of parsers

The syntax should be nice for its users. I don't think I should have to care about whether the parser is nice or not 😀

Bounded lookahead is very convenient

I think that the syntax should be very convenient for its users / for web developers.

The potential performance hit should get verified before the API makes amends - the actual perf hit in real-world stylesheets might be negligible.

tobireif commented Jun 1, 2018

it also just rules out certain nice classes of parsers

The syntax should be nice for its users. I don't think I should have to care about whether the parser is nice or not 😀

Bounded lookahead is very convenient

I think that the syntax should be very convenient for its users / for web developers.

The potential performance hit should get verified before the API makes amends - the actual perf hit in real-world stylesheets might be negligible.

@jonathantneal

This comment has been minimized.

Show comment
Hide comment
@jonathantneal

jonathantneal Jun 1, 2018

Contributor

@tobireif, have you experimented with nesting in a manner that reflects the current spec? While it isn’t 1:1 like Sass, I eventually preferred it because it was easy to scan and explicit without adding many characters (typically only one, &):

#main {
  color: black;

  & a {
    font-weight: bold;
  }

  @nest main > & {
    color: navy;
  }
}

You can experiment with it here: https://preset-env.cssdb.org/playground (I hope everyone will forgive my sharing that link, as I try hard not to seem like a salesperson.)

Contributor

jonathantneal commented Jun 1, 2018

@tobireif, have you experimented with nesting in a manner that reflects the current spec? While it isn’t 1:1 like Sass, I eventually preferred it because it was easy to scan and explicit without adding many characters (typically only one, &):

#main {
  color: black;

  & a {
    font-weight: bold;
  }

  @nest main > & {
    color: navy;
  }
}

You can experiment with it here: https://preset-env.cssdb.org/playground (I hope everyone will forgive my sharing that link, as I try hard not to seem like a salesperson.)

@LeaVerou

This comment has been minimized.

Show comment
Hide comment
@LeaVerou

LeaVerou Jun 1, 2018

Contributor

@tobireif I sympathize with the usability concerns you are expressing (especially since usability is my research area). However, in this group we tend to take implementor concerns very seriously into account. Specs that are not implementable are just pointless fantasy documents. If you want to argue that the ampersand should not be required, a technical argument about how to implement that within bounded lookahead would be more effective than a philosophical argument. Also do note that the current spec does not prevent making the ampersand optional in the future, if a good way to implement that performantly comes up.

Contributor

LeaVerou commented Jun 1, 2018

@tobireif I sympathize with the usability concerns you are expressing (especially since usability is my research area). However, in this group we tend to take implementor concerns very seriously into account. Specs that are not implementable are just pointless fantasy documents. If you want to argue that the ampersand should not be required, a technical argument about how to implement that within bounded lookahead would be more effective than a philosophical argument. Also do note that the current spec does not prevent making the ampersand optional in the future, if a good way to implement that performantly comes up.

@LeaVerou

This comment has been minimized.

Show comment
Hide comment
@LeaVerou

LeaVerou Jun 1, 2018

Contributor

@tabatkins Can we allow relative selectors to this? That would reduce the characters needed, and descendants could be specified as >> foo. Since no properties start with combinators, that should not interfere with bounded lookahead.

Contributor

LeaVerou commented Jun 1, 2018

@tabatkins Can we allow relative selectors to this? That would reduce the characters needed, and descendants could be specified as >> foo. Since no properties start with combinators, that should not interfere with bounded lookahead.

@tabatkins

This comment has been minimized.

Show comment
Hide comment
@tabatkins

tabatkins Jun 1, 2018

Member

That's theoretically possible, sure; no grammar problems with it. But it means that now there's 3 nesting forms: if you're nesting with a combinator, use it directly (but you can use & if you want); if you're nesting by just adding more selectors, you have to use &; if you're doing anything more complicated, you have to use @nest.

The current rules are simpler - when you nest, you need to produce a full new selector with a & in it, referring to whatever's matched by the parent selector; if the & isn't the very first thing, you have to use @nest. The requirement is straightforward, and the condition for changing to @nest is visually obvious. I think this simplicity is pretty valuable!

Member

tabatkins commented Jun 1, 2018

That's theoretically possible, sure; no grammar problems with it. But it means that now there's 3 nesting forms: if you're nesting with a combinator, use it directly (but you can use & if you want); if you're nesting by just adding more selectors, you have to use &; if you're doing anything more complicated, you have to use @nest.

The current rules are simpler - when you nest, you need to produce a full new selector with a & in it, referring to whatever's matched by the parent selector; if the & isn't the very first thing, you have to use @nest. The requirement is straightforward, and the condition for changing to @nest is visually obvious. I think this simplicity is pretty valuable!

@LeaVerou

This comment has been minimized.

Show comment
Hide comment
@LeaVerou

LeaVerou Jun 5, 2018

Contributor

Alternatively, the only ambiguous case is when the selector starts with an element selector, right? If it starts with an id, class, pseudo-class, or pseudo-element, we know immediately.
What if the ampersand was only required in that case?
This will simplify a ton of cases. It has the drawback if being a little less consistent but then again, so was requiring whitespace around + and - in calc(), but we did that. 😁

Contributor

LeaVerou commented Jun 5, 2018

Alternatively, the only ambiguous case is when the selector starts with an element selector, right? If it starts with an id, class, pseudo-class, or pseudo-element, we know immediately.
What if the ampersand was only required in that case?
This will simplify a ton of cases. It has the drawback if being a little less consistent but then again, so was requiring whitespace around + and - in calc(), but we did that. 😁

@FremyCompany

This comment has been minimized.

Show comment
Hide comment
@FremyCompany

FremyCompany Jun 6, 2018

Contributor

I don't see strong reason to change the current spec.

Contributor

FremyCompany commented Jun 6, 2018

I don't see strong reason to change the current spec.

@fantasai

This comment has been minimized.

Show comment
Hide comment
@fantasai

fantasai Jun 6, 2018

Contributor

I would like to see a discussion from the authoring perspective on Nesting vs Scoping and whether one is better or both are needed or what.

It's clear to me that people don't like repeating selectors, but it's less clear to me whether the desire for nesting is related to manipulating the cascade as well (which is poorly done via nesting, and better done via scoping) or the current specificity effects are exactly what's desired and only a syntactic manipulation is wanted.

As a review: Nesting merely adds up the specificities of the selectors which are chained together. (It's just a syntactic manipulation, which can be done with a preprocessor.) With Scoping, “The specificity of selectors inside the @scope rule is calculated locally: the selector specifying the scoping element is ignored. However, because scoped styles override non-scoped styles, style rules inside the @scope will override rules outside of it.” (If multiple @scopeed rules apply to an element, the rule with the deepest scoping element wins. See details in Cascade.)

Contributor

fantasai commented Jun 6, 2018

I would like to see a discussion from the authoring perspective on Nesting vs Scoping and whether one is better or both are needed or what.

It's clear to me that people don't like repeating selectors, but it's less clear to me whether the desire for nesting is related to manipulating the cascade as well (which is poorly done via nesting, and better done via scoping) or the current specificity effects are exactly what's desired and only a syntactic manipulation is wanted.

As a review: Nesting merely adds up the specificities of the selectors which are chained together. (It's just a syntactic manipulation, which can be done with a preprocessor.) With Scoping, “The specificity of selectors inside the @scope rule is calculated locally: the selector specifying the scoping element is ignored. However, because scoped styles override non-scoped styles, style rules inside the @scope will override rules outside of it.” (If multiple @scopeed rules apply to an element, the rule with the deepest scoping element wins. See details in Cascade.)

@css-meeting-bot

This comment has been minimized.

Show comment
Hide comment
@css-meeting-bot

css-meeting-bot Jun 7, 2018

Member

The Working Group just discussed request to pick up the css-nesting proposal.

The full IRC log of that discussion <dael> Topic: request to pick up the css-nesting proposal
<dael> github: https://github.com/w3c/csswg-drafts/issues/2701
<dael> TabAtkins: The proposal is relatively simple. Wrote a spec a few years back. I'm fine but it's a syntax nicity where we didn't get it past hte community. If that's changed we can move it forward
<dael> fantasai: leaverou comment talks about wanting different specificity handling or the cascade. That's not syntactic only where you can do it wwith a preprocessor. There was @scope proposal before. I don't know if that's wanted still. I want to see more of that discussed. Do we want to effect cascade, if yes how. If we do this we should find out what's desired.
<dael> TabAtkins: I strongly believe nothing new on specificity. b/c nesting is in every preprocessor in existance doing so would be a major behavior change.
<dael> fantasai: No, not with same syntax.
<dael> TabAtkins: Second reason is it wouldn't be same as @Scoped and it would produce thigns that some ways resembe but some way don't. @Scoped wasn't popular and doesn't do what people want for scoping.
<dael> leaverou: I agree with TabAtkins, people are used to using nesting for preprocessors. I dsiagree with my earlier comment. I think scoping is useful, Not sure usability of scoping prop. It shouldn't hold nesting back.
<dael> TabAtkins: Happy to have that separate.
<dael> astearns: Objections to working on a purely syntactic nesting proposal
<dael> astearns: One concern is if you can do it in a preprocessor why do it, but even the preprocessor authors are asking us to do it.
<dael> chris: preprocessor expands to a ton of stuff and we don't want that expansion
<gsnedders> It's one less reason to use a preprocessor, IMO.
<gsnedders> And that's a good thing.
<fantasai> s/wanted still/wanted or something different/
<dael> astearns: Maybe an issue that we want to avoid the exposion of conbinations that can happens
<bkardell_> better for authors, better for network, very slightly worse for processing perf maybe?
<dael> florian: For OM representation yes, but effect that's unavoidable
<dael> TabAtkins: CSS style rules gain a child. OM doesn't explode
<dael> chris: That's a big advantage
<dael> leaverou: Huge advantage you can fo hover or focus styles on a one off
<dael> TabAtkins: Originally a proposal to do rules inside style attribute and this doens't have that. You need only one token of look ahead.
<dael> astearns: Obj to resolving we want to move forward with pure syntactic nesting?
<dael> TabAtkins: And I want the impl to say if they actually don't want it.
<tantek_> I'm too confused to comment on this last minute on the call
<dael> dbaron: If you're discussing changing what's in proposal it would be good to have that written to share around
<dael> TabAtkins: Entire proposal is linked in the issue to a spec on my personal github. It's laid out with no odd changes
<dael> TabAtkins: We can go to next week
<dael> astearns: We're over time. I don't hear obj. I think we are going to move forward, but let's give people time and we'll come back.
<dbaron> I think for Gecko implementation it's probably worth asking heycam and emilio rather than me.
Member

css-meeting-bot commented Jun 7, 2018

The Working Group just discussed request to pick up the css-nesting proposal.

The full IRC log of that discussion <dael> Topic: request to pick up the css-nesting proposal
<dael> github: https://github.com/w3c/csswg-drafts/issues/2701
<dael> TabAtkins: The proposal is relatively simple. Wrote a spec a few years back. I'm fine but it's a syntax nicity where we didn't get it past hte community. If that's changed we can move it forward
<dael> fantasai: leaverou comment talks about wanting different specificity handling or the cascade. That's not syntactic only where you can do it wwith a preprocessor. There was @scope proposal before. I don't know if that's wanted still. I want to see more of that discussed. Do we want to effect cascade, if yes how. If we do this we should find out what's desired.
<dael> TabAtkins: I strongly believe nothing new on specificity. b/c nesting is in every preprocessor in existance doing so would be a major behavior change.
<dael> fantasai: No, not with same syntax.
<dael> TabAtkins: Second reason is it wouldn't be same as @Scoped and it would produce thigns that some ways resembe but some way don't. @Scoped wasn't popular and doesn't do what people want for scoping.
<dael> leaverou: I agree with TabAtkins, people are used to using nesting for preprocessors. I dsiagree with my earlier comment. I think scoping is useful, Not sure usability of scoping prop. It shouldn't hold nesting back.
<dael> TabAtkins: Happy to have that separate.
<dael> astearns: Objections to working on a purely syntactic nesting proposal
<dael> astearns: One concern is if you can do it in a preprocessor why do it, but even the preprocessor authors are asking us to do it.
<dael> chris: preprocessor expands to a ton of stuff and we don't want that expansion
<gsnedders> It's one less reason to use a preprocessor, IMO.
<gsnedders> And that's a good thing.
<fantasai> s/wanted still/wanted or something different/
<dael> astearns: Maybe an issue that we want to avoid the exposion of conbinations that can happens
<bkardell_> better for authors, better for network, very slightly worse for processing perf maybe?
<dael> florian: For OM representation yes, but effect that's unavoidable
<dael> TabAtkins: CSS style rules gain a child. OM doesn't explode
<dael> chris: That's a big advantage
<dael> leaverou: Huge advantage you can fo hover or focus styles on a one off
<dael> TabAtkins: Originally a proposal to do rules inside style attribute and this doens't have that. You need only one token of look ahead.
<dael> astearns: Obj to resolving we want to move forward with pure syntactic nesting?
<dael> TabAtkins: And I want the impl to say if they actually don't want it.
<tantek_> I'm too confused to comment on this last minute on the call
<dael> dbaron: If you're discussing changing what's in proposal it would be good to have that written to share around
<dael> TabAtkins: Entire proposal is linked in the issue to a spec on my personal github. It's laid out with no odd changes
<dael> TabAtkins: We can go to next week
<dael> astearns: We're over time. I don't hear obj. I think we are going to move forward, but let's give people time and we'll come back.
<dbaron> I think for Gecko implementation it's probably worth asking heycam and emilio rather than me.

@astearns astearns removed the Agenda+ label Jun 7, 2018

@AmeliaBR

This comment has been minimized.

Show comment
Hide comment
@AmeliaBR

AmeliaBR Jun 7, 2018

Happy to see this moving forward into deeper discussion!

But as I review @tabatkins draft, here are some issues that jump out to me:

  1. Based on the recent decision to change how :matches() specificity works (#1027), we would need to decide whether a, b { & c {prop:val}} expands as a c, b c {prop: val} or as :matches(a,b) c {prop: val} (which could for some values of a and b result in different specificity than how it works with pre-processors). Then, all examples would need to be updated to consistently use one expansion or the other.

  2. It's worth calling out that Tab's proposed & is less powerful than the SCSS &. I understand the parsing reasons for the limitations, but it means you won't be able to blindly convert all SCSS nesting code to plain nested CSS.

    Some examples of SCSS features which wouldn't be supported in the proposal (P.S. Useful reference to SCSS nesting, for comparison):

    • Omitting the & for parent-child relationships.

    • Allowing the & anywhere in the selector, like:

      :link { .container & {/* link styles inside that container */} }
      

      In Tab's proposal, you could create this functionality with an explicit @nest rule:

      :link { @nest .container & {/* link styles inside that container */} }
      
    • Extending a single selector token, for example to create BEM-style modified classes like:

      .block { &__elem { &--modifier { /*styles*/ } } }
      

      which in SCSS compiles to a single class:

      .block__elem--modifier { /* styles */ }
      

      I don't think this would be supported at all in Tab's proposal, since it requires merging tokens after parsing.

  3. This looks like something that could be an implementation issue and/or a source of authoring issues:

    The relative ordering of nested style rules and other declarations is important; it’s possible for a given style rule and a nested style rule within it to match the same element, and if the specificity of the two rules is otherwise equivalent, the relative order in the stylesheet of the applicable declarations determines which declaration "wins" the cascade.

    CSS in many places requires a very clear ordering of individual rules. For example, you can't @import one stylesheet halfway through another one, because all the rules in one need to be before or after all the rules in. This would create half of a style rule having lower precedence than another rule, and half of it having higher precedence.

    It also would create another situation where the result with preprocessors (which must always turn nested rules into sibling rules) would be different from the result with the new syntax.

    An intentionally trivial example, to be sure that the two selectors have equal specificity:

    body { 
      color: indigo;
      * & { 
        color: cyan;
        background-color: red; 
      }
      background-color: blue;  
    }

    In SCSS, the nested rule compiles to come after the outer rule, and the page is cyan text on red. In Tab's proposal it would be cyan text on blue.

Points 1 and 3 of that list can probably be discussed as proper issues as soon as [css-nesting] is converted to a proper draft spec. Point 2 is more of a head's-up for anyone getting excited about Sass nesting coming to CSS.

AmeliaBR commented Jun 7, 2018

Happy to see this moving forward into deeper discussion!

But as I review @tabatkins draft, here are some issues that jump out to me:

  1. Based on the recent decision to change how :matches() specificity works (#1027), we would need to decide whether a, b { & c {prop:val}} expands as a c, b c {prop: val} or as :matches(a,b) c {prop: val} (which could for some values of a and b result in different specificity than how it works with pre-processors). Then, all examples would need to be updated to consistently use one expansion or the other.

  2. It's worth calling out that Tab's proposed & is less powerful than the SCSS &. I understand the parsing reasons for the limitations, but it means you won't be able to blindly convert all SCSS nesting code to plain nested CSS.

    Some examples of SCSS features which wouldn't be supported in the proposal (P.S. Useful reference to SCSS nesting, for comparison):

    • Omitting the & for parent-child relationships.

    • Allowing the & anywhere in the selector, like:

      :link { .container & {/* link styles inside that container */} }
      

      In Tab's proposal, you could create this functionality with an explicit @nest rule:

      :link { @nest .container & {/* link styles inside that container */} }
      
    • Extending a single selector token, for example to create BEM-style modified classes like:

      .block { &__elem { &--modifier { /*styles*/ } } }
      

      which in SCSS compiles to a single class:

      .block__elem--modifier { /* styles */ }
      

      I don't think this would be supported at all in Tab's proposal, since it requires merging tokens after parsing.

  3. This looks like something that could be an implementation issue and/or a source of authoring issues:

    The relative ordering of nested style rules and other declarations is important; it’s possible for a given style rule and a nested style rule within it to match the same element, and if the specificity of the two rules is otherwise equivalent, the relative order in the stylesheet of the applicable declarations determines which declaration "wins" the cascade.

    CSS in many places requires a very clear ordering of individual rules. For example, you can't @import one stylesheet halfway through another one, because all the rules in one need to be before or after all the rules in. This would create half of a style rule having lower precedence than another rule, and half of it having higher precedence.

    It also would create another situation where the result with preprocessors (which must always turn nested rules into sibling rules) would be different from the result with the new syntax.

    An intentionally trivial example, to be sure that the two selectors have equal specificity:

    body { 
      color: indigo;
      * & { 
        color: cyan;
        background-color: red; 
      }
      background-color: blue;  
    }

    In SCSS, the nested rule compiles to come after the outer rule, and the page is cyan text on red. In Tab's proposal it would be cyan text on blue.

Points 1 and 3 of that list can probably be discussed as proper issues as soon as [css-nesting] is converted to a proper draft spec. Point 2 is more of a head's-up for anyone getting excited about Sass nesting coming to CSS.

@tabatkins

This comment has been minimized.

Show comment
Hide comment
@tabatkins

tabatkins Jun 7, 2018

Member

we would need to decide whether a, b { & c {prop:val}} expands as a c, b c {prop: val} or as :matches(a,b) c {prop: val}

The draft currently specifies it as the latter, and I find it very unlikely that we'd change off from that. Changing would require either actually expanding under the hood (with the attendant multiplicative blowup), or implementing the careful actually-matched-path logic that we explicitly rejected forcing implementors to use for :matches().

It's worth calling out that Tab's proposed & is less powerful than the SCSS &.

Agreed, I can add a section to the intro about this.

Omitting the & for parent-child relationships.

Intentional, as I don't want to privilege the descendant combinator, and I personally think it's less clear what's going on.

Extending a single selector token, for example to create BEM-style modified classes

Yeah, very intentionally not allowed. It causes parsing issues, for one (you can't arbitrarily split up an ident and be guaranteed that both halves are still idents), and it's grammatically ambiguous with tagname selectors.

[Relative ordering of declarations and nested rules in a single style rule] looks like something that could be an implementation issue and/or a source of authoring issues:

Yeah, I think I need to change that to sort the declarations to the front. Otherwise I have to reflect the relative ordering of declarations and rules in the OM, which'll be nasty and not compatible with my current plans of just adding a .childRules property to CSSStyleRule.

Member

tabatkins commented Jun 7, 2018

we would need to decide whether a, b { & c {prop:val}} expands as a c, b c {prop: val} or as :matches(a,b) c {prop: val}

The draft currently specifies it as the latter, and I find it very unlikely that we'd change off from that. Changing would require either actually expanding under the hood (with the attendant multiplicative blowup), or implementing the careful actually-matched-path logic that we explicitly rejected forcing implementors to use for :matches().

It's worth calling out that Tab's proposed & is less powerful than the SCSS &.

Agreed, I can add a section to the intro about this.

Omitting the & for parent-child relationships.

Intentional, as I don't want to privilege the descendant combinator, and I personally think it's less clear what's going on.

Extending a single selector token, for example to create BEM-style modified classes

Yeah, very intentionally not allowed. It causes parsing issues, for one (you can't arbitrarily split up an ident and be guaranteed that both halves are still idents), and it's grammatically ambiguous with tagname selectors.

[Relative ordering of declarations and nested rules in a single style rule] looks like something that could be an implementation issue and/or a source of authoring issues:

Yeah, I think I need to change that to sort the declarations to the front. Otherwise I have to reflect the relative ordering of declarations and rules in the OM, which'll be nasty and not compatible with my current plans of just adding a .childRules property to CSSStyleRule.

@tabatkins

This comment has been minimized.

Show comment
Hide comment
@tabatkins

tabatkins Jun 7, 2018

Member

Alternatively, the only ambiguous case is when the selector starts with an element selector, right? If it starts with an id, class, pseudo-class, or pseudo-element, we know immediately.

What if the ampersand was only required in that case?

This will simplify a ton of cases. It has the drawback if being a little less consistent but then again, so was requiring whitespace around + and - in calc(), but we did that.

It's still drawing a more complicated boundary around "what's allowed without @nest", and more damningly, the reasoning behind the boundary is relatively arcane parsing concerns, far below the level that an author should have to learn about. This means the boundary will feel arbitrary to authors, which is a big strike against in terms of learnability and usability.

Additionally, in current preprocessors .foo { .bar {...}} already has a meaning - it's equivalent to .foo .bar {...}. It's ambiguous what this should mean in Nesting - is it equivalent to &.bar or & .bar?

If there really was a big usability benefit from being able to omit the & I'd be more willing to consider the tradeoffs, but it's a single character to type, and it makes things less ambiguous anyway. I don't think any exceptions here are worth their weight.

Member

tabatkins commented Jun 7, 2018

Alternatively, the only ambiguous case is when the selector starts with an element selector, right? If it starts with an id, class, pseudo-class, or pseudo-element, we know immediately.

What if the ampersand was only required in that case?

This will simplify a ton of cases. It has the drawback if being a little less consistent but then again, so was requiring whitespace around + and - in calc(), but we did that.

It's still drawing a more complicated boundary around "what's allowed without @nest", and more damningly, the reasoning behind the boundary is relatively arcane parsing concerns, far below the level that an author should have to learn about. This means the boundary will feel arbitrary to authors, which is a big strike against in terms of learnability and usability.

Additionally, in current preprocessors .foo { .bar {...}} already has a meaning - it's equivalent to .foo .bar {...}. It's ambiguous what this should mean in Nesting - is it equivalent to &.bar or & .bar?

If there really was a big usability benefit from being able to omit the & I'd be more willing to consider the tradeoffs, but it's a single character to type, and it makes things less ambiguous anyway. I don't think any exceptions here are worth their weight.

@tabatkins

This comment has been minimized.

Show comment
Hide comment
@tabatkins

tabatkins Jun 7, 2018

Member

It's clear to me that people don't like repeating selectors, but it's less clear to me whether the desire for nesting is related to manipulating the cascade as well (which is poorly done via nesting, and better done via scoping) or the current specificity effects are exactly what's desired and only a syntactic manipulation is wanted.

I think a lot of chatter has led us to the conclusion that people mostly don't like specificity much in the first place, so adding more specificity confusion probably isn't good here. ^_^

More importantly, Nesting is so useful as a simple syntactic device that it'll get used solely for readability/maintainability reasons, and layering extra specificity behavior on top of it would cause confusion, I think.

(Plus, as described this isn't Scoping-equivalent anyway. Scoping had a particular element it was scoped to, so it could accurately guard against other scoped rules coming from higher in the tree, and yield to scoped rules coming from lower in the tree. Just attaching scoping-ish behavior to an arbitrary selector doesn't give the same easy mental model.)

Member

tabatkins commented Jun 7, 2018

It's clear to me that people don't like repeating selectors, but it's less clear to me whether the desire for nesting is related to manipulating the cascade as well (which is poorly done via nesting, and better done via scoping) or the current specificity effects are exactly what's desired and only a syntactic manipulation is wanted.

I think a lot of chatter has led us to the conclusion that people mostly don't like specificity much in the first place, so adding more specificity confusion probably isn't good here. ^_^

More importantly, Nesting is so useful as a simple syntactic device that it'll get used solely for readability/maintainability reasons, and layering extra specificity behavior on top of it would cause confusion, I think.

(Plus, as described this isn't Scoping-equivalent anyway. Scoping had a particular element it was scoped to, so it could accurately guard against other scoped rules coming from higher in the tree, and yield to scoped rules coming from lower in the tree. Just attaching scoping-ish behavior to an arbitrary selector doesn't give the same easy mental model.)

@jonathantneal

This comment has been minimized.

Show comment
Hide comment
@jonathantneal

jonathantneal Jun 7, 2018

Contributor

As an author who adopted the syntax outlined in this specification with a transpiler, I can say that my teams found ampersand nesting more readable than Sass nesting. Once implemented, my transpiler received no complaints as to this requirement, that I recall.

I’ll sober that opinion by acknowledging that I’m not sure what 400k weekly installs actually translates to in ”users who would actually report issues”. I’m just saying — this spec has a reasonable number of early adopters.

What users did complain about on occasion was the lack of selector concatenation (e.g. &-modified-classname). However, I believe the spec got it right, both for the reasons Tab has mentioned, and also for the reasons mentioned by a notable Sass expert, Hugo Giraudel, who made several arguments against ampersand concatenation, which he demonstrated lead to naturally ambiguous selectors that actually hinder authors.

Anyway, I would echo what @FremyCompany has said; from my point of view I don't see strong reason to change the current spec. I’m so glad to see it being considered.

Contributor

jonathantneal commented Jun 7, 2018

As an author who adopted the syntax outlined in this specification with a transpiler, I can say that my teams found ampersand nesting more readable than Sass nesting. Once implemented, my transpiler received no complaints as to this requirement, that I recall.

I’ll sober that opinion by acknowledging that I’m not sure what 400k weekly installs actually translates to in ”users who would actually report issues”. I’m just saying — this spec has a reasonable number of early adopters.

What users did complain about on occasion was the lack of selector concatenation (e.g. &-modified-classname). However, I believe the spec got it right, both for the reasons Tab has mentioned, and also for the reasons mentioned by a notable Sass expert, Hugo Giraudel, who made several arguments against ampersand concatenation, which he demonstrated lead to naturally ambiguous selectors that actually hinder authors.

Anyway, I would echo what @FremyCompany has said; from my point of view I don't see strong reason to change the current spec. I’m so glad to see it being considered.

@chriseppstein

This comment has been minimized.

Show comment
Hide comment
@chriseppstein

chriseppstein Jun 7, 2018

Extending a single selector token, for example to create BEM-style modified classes

Yeah, very intentionally not allowed. It causes parsing issues...

This is one of the few features in Sass that I sincerely regret adding. It was a bad idea. We had a lot of reservations about it. But the request was so common we decided to give in to popular demand. Since then, I've seen many issues that showed me that we did fundamentally make a mistake by allowing appending to the current token(s) represented by &.

Tab says this is about parsing issues and as is argued above "The syntax should be nice for its users. I don't think I should have to care about whether the parser is nice or not". But I've seen sufficient issues at this point to say that those parsing issues are not independent of what authors experience as confusing. For instance: the @extend directive in Sass is applied after nesting is resolved. This means that extending the first token of an ident that has an appended token in a nested selector only ends up affecting outer ruleset's selector. But many authors expect it to also affect the child selectors. E.g. they expect .foo { color: red; &__bar { color: blue }} .inherits { @extend .foo; } to produce .foo, .inherits and .foo__bar, .inherits__bar, but .inherits__bar is not produced by that code. If we had adhered to the token boundary rule this would not be a problem authors.

If there really was a big usability benefit from being able to omit the & I'd be more willing to consider the tradeoffs, but it's a single character to type, and it makes things less ambiguous anyway. I don't think any exceptions here are worth their weight.

I agree, @tabatkins.

In Tab's proposal it would be cyan text on blue.

Tab got this right. Sass's behavior in this context was defined very early on and the output was not well considered and mostly just that way because the implementation was easier to write. The correct output for Sass should have been:

body { 
  color: indigo;
}
* body { 
  color: cyan;
  background-color: red; 
}
body { 
  background-color: blue;  
}

instead of introducing a change to the author's document order.

If this spec gets traction, I will recommend that we change Sass: Deprecate the current capability by first disallowing any trailing declarations after nesting and then matching this spec's behavior in a future release.

Allowing the & anywhere in the selector.

As stated, the parsing lookahead is bad for browsers. This is a place where preprocessors can still add value. There's no reason Sass can't output @nest for a selector that contains & that isn't the leading token, once Sass can reliably target browsers with this capability in its output (or via a browserlist query, etc). PostCSS can do this too.

Extending a single selector token, for example to create BEM-style modified classes

Yeah, very intentionally not allowed. It causes parsing issues...

This is one of the few features in Sass that I sincerely regret adding. It was a bad idea. We had a lot of reservations about it. But the request was so common we decided to give in to popular demand. Since then, I've seen many issues that showed me that we did fundamentally make a mistake by allowing appending to the current token(s) represented by &.

Tab says this is about parsing issues and as is argued above "The syntax should be nice for its users. I don't think I should have to care about whether the parser is nice or not". But I've seen sufficient issues at this point to say that those parsing issues are not independent of what authors experience as confusing. For instance: the @extend directive in Sass is applied after nesting is resolved. This means that extending the first token of an ident that has an appended token in a nested selector only ends up affecting outer ruleset's selector. But many authors expect it to also affect the child selectors. E.g. they expect .foo { color: red; &__bar { color: blue }} .inherits { @extend .foo; } to produce .foo, .inherits and .foo__bar, .inherits__bar, but .inherits__bar is not produced by that code. If we had adhered to the token boundary rule this would not be a problem authors.

If there really was a big usability benefit from being able to omit the & I'd be more willing to consider the tradeoffs, but it's a single character to type, and it makes things less ambiguous anyway. I don't think any exceptions here are worth their weight.

I agree, @tabatkins.

In Tab's proposal it would be cyan text on blue.

Tab got this right. Sass's behavior in this context was defined very early on and the output was not well considered and mostly just that way because the implementation was easier to write. The correct output for Sass should have been:

body { 
  color: indigo;
}
* body { 
  color: cyan;
  background-color: red; 
}
body { 
  background-color: blue;  
}

instead of introducing a change to the author's document order.

If this spec gets traction, I will recommend that we change Sass: Deprecate the current capability by first disallowing any trailing declarations after nesting and then matching this spec's behavior in a future release.

Allowing the & anywhere in the selector.

As stated, the parsing lookahead is bad for browsers. This is a place where preprocessors can still add value. There's no reason Sass can't output @nest for a selector that contains & that isn't the leading token, once Sass can reliably target browsers with this capability in its output (or via a browserlist query, etc). PostCSS can do this too.

@tobireif

This comment has been minimized.

Show comment
Hide comment
@tobireif

tobireif Jun 8, 2018

It's just a syntactic manipulation, which can be done with a preprocessor.

I stopped using preprocessors (except when it's decided to use one, eg in a team project).

This is a place where preprocessors can still add value.

I want powerful and full-featured native nesting, without using any kind of preprocessor.

tobireif commented Jun 8, 2018

It's just a syntactic manipulation, which can be done with a preprocessor.

I stopped using preprocessors (except when it's decided to use one, eg in a team project).

This is a place where preprocessors can still add value.

I want powerful and full-featured native nesting, without using any kind of preprocessor.

@jonjohnjohnson

This comment has been minimized.

Show comment
Hide comment
@jonjohnjohnson

jonjohnjohnson Jun 8, 2018

IMO Preprocessors always have a place in development workflow. -> "Don’t do it at runtime. Do it at design time." And I'm generally happy with the current version of the spec.

IMO Preprocessors always have a place in development workflow. -> "Don’t do it at runtime. Do it at design time." And I'm generally happy with the current version of the spec.

@battaglr

This comment has been minimized.

Show comment
Hide comment
@battaglr

battaglr Jun 8, 2018

Please, don't do this. I have only seen abuse and misuse of this feature in almost every project I have been involved with.

battaglr commented Jun 8, 2018

Please, don't do this. I have only seen abuse and misuse of this feature in almost every project I have been involved with.

@LeaVerou

This comment has been minimized.

Show comment
Hide comment
@LeaVerou

LeaVerou Jun 8, 2018

Contributor

Please, don't do this. I have only seen abuse and misuse of this feature in almost every project I have been involved with.

If you could elaborate on the kind of abuse and misuse you have seen, that would be far more useful input to the discussion.

Contributor

LeaVerou commented Jun 8, 2018

Please, don't do this. I have only seen abuse and misuse of this feature in almost every project I have been involved with.

If you could elaborate on the kind of abuse and misuse you have seen, that would be far more useful input to the discussion.

@tobireif

This comment has been minimized.

Show comment
Hide comment
@tobireif

tobireif Jun 9, 2018

IMO Preprocessors always have a place in development workflow.

Not in mine. (Unless it has been decided to use a preprocessor, eg in a client project / team project).

I didn't (and would never) state in general terms that every development workflow should use a preprocessor, or that preprocessors should never be part of any development workflow. Instead I was and am talking for myself.

I'm happy that preprocessors are less and less necessary since CSS supports more and more natively. Yay for powerful & pure CSS 😀

tobireif commented Jun 9, 2018

IMO Preprocessors always have a place in development workflow.

Not in mine. (Unless it has been decided to use a preprocessor, eg in a client project / team project).

I didn't (and would never) state in general terms that every development workflow should use a preprocessor, or that preprocessors should never be part of any development workflow. Instead I was and am talking for myself.

I'm happy that preprocessors are less and less necessary since CSS supports more and more natively. Yay for powerful & pure CSS 😀

@jonathantneal

This comment has been minimized.

Show comment
Hide comment
@jonathantneal

jonathantneal Jun 9, 2018

Contributor

@battaglr, you responded similarly to a Twitter thread linking here, where the 2 raised complaints were how nesting can lead to:

  1. ambiguous and unsearchable selectors via raw appending (&-bem-class); and,
  2. unnecessarily and deeply nested selectors (& foo { & bar { & qux { & etc {} } } }.

Here is a link to that thread: https://twitter.com/jon_neal/status/1004962076824145921, and please let me know if I am misrepresenting your concerns, Luciano.

I think both are worthy complaints. Thankfully, the spec does not allow arbitrary selector appending like Sass. This is even considered a mistake in Sass. This will be a non-issue. 😄🎉

I see the second complaint as a pro and a con. Nesting would make writing CSS selector chains a lot easier, and that could lead to poorly written CSS. However, these selectors would not be technically worse than what one can already do by writing out long, complex CSS selectors. I think Sass has proven these benefits and abuses, which means we can better provide author guidance.

Used wisely or unwisely, nesting would offer authors less selector repetition and more structurally organized rules.

Contributor

jonathantneal commented Jun 9, 2018

@battaglr, you responded similarly to a Twitter thread linking here, where the 2 raised complaints were how nesting can lead to:

  1. ambiguous and unsearchable selectors via raw appending (&-bem-class); and,
  2. unnecessarily and deeply nested selectors (& foo { & bar { & qux { & etc {} } } }.

Here is a link to that thread: https://twitter.com/jon_neal/status/1004962076824145921, and please let me know if I am misrepresenting your concerns, Luciano.

I think both are worthy complaints. Thankfully, the spec does not allow arbitrary selector appending like Sass. This is even considered a mistake in Sass. This will be a non-issue. 😄🎉

I see the second complaint as a pro and a con. Nesting would make writing CSS selector chains a lot easier, and that could lead to poorly written CSS. However, these selectors would not be technically worse than what one can already do by writing out long, complex CSS selectors. I think Sass has proven these benefits and abuses, which means we can better provide author guidance.

Used wisely or unwisely, nesting would offer authors less selector repetition and more structurally organized rules.

@jonathantneal jonathantneal referenced this issue in csstools/postcss-preset-env Jun 11, 2018

Closed

Nesting with special char ? #40

@battaglr

This comment has been minimized.

Show comment
Hide comment
@battaglr

battaglr Jun 14, 2018

You're right @LeaVerou, I should have made a more productive comment, but honestly felt that @tabatkins already covered most of the "issues" I have with this feature. To be more specific: (a) privileges the descendant combinator, (b) could be used just for the cosmetic reasons —i.e. to increase readability, which is arguable depending on the size of the parent rule— and increase specificity unnecessarily, (c) many people thinks that nesting is the "right way" to use a preprocessor/transpiler, (d) many people tends to think that nesting should be used to replicate the DOM structure. I have done far so many code reviews and talked with so many devs that made this mistakes over and over that, to be honest, I have grown a sentiment of dislike for this feature. I understand it has more to do with less experienced devs using it for the wrong reasons than a problem with the feature itself.

Thank you very much @jonathantneal, you interpreted my concerns perfectly.

However, these selectors would not be technically worse than what one can already do by writing out long, complex CSS selectors.

I agree. But with nesting writing "bad selectors" it's easier and "feels" less bad.

This will probably not raise many concerns:

.foo {
  /* .. */
  & .bar {
    /* .. */
    & .baz {
      /* .. */
    }
  }

  & .qux {
    /* .. */
    & .quz {
      /* .. */
    }
  }
}

This will probably be called out in a code review:

.foo {
  /* .. */
}
.foo .bar {
  /* .. */
}
.foo .bar .baz {
  /* .. */
}
.foo .qux {
  /* .. */
}
.foo .qux .quz {
  /* .. */
}

Again, my reasons are totally subjective and I don't think that the feature itself is bad —to be really honest I don't find it useful since I tend to "nest" in very rare occasions— rather that it could be easily abused and misused —at least in my experience.

Hope this adds to the conversation. 😀

battaglr commented Jun 14, 2018

You're right @LeaVerou, I should have made a more productive comment, but honestly felt that @tabatkins already covered most of the "issues" I have with this feature. To be more specific: (a) privileges the descendant combinator, (b) could be used just for the cosmetic reasons —i.e. to increase readability, which is arguable depending on the size of the parent rule— and increase specificity unnecessarily, (c) many people thinks that nesting is the "right way" to use a preprocessor/transpiler, (d) many people tends to think that nesting should be used to replicate the DOM structure. I have done far so many code reviews and talked with so many devs that made this mistakes over and over that, to be honest, I have grown a sentiment of dislike for this feature. I understand it has more to do with less experienced devs using it for the wrong reasons than a problem with the feature itself.

Thank you very much @jonathantneal, you interpreted my concerns perfectly.

However, these selectors would not be technically worse than what one can already do by writing out long, complex CSS selectors.

I agree. But with nesting writing "bad selectors" it's easier and "feels" less bad.

This will probably not raise many concerns:

.foo {
  /* .. */
  & .bar {
    /* .. */
    & .baz {
      /* .. */
    }
  }

  & .qux {
    /* .. */
    & .quz {
      /* .. */
    }
  }
}

This will probably be called out in a code review:

.foo {
  /* .. */
}
.foo .bar {
  /* .. */
}
.foo .bar .baz {
  /* .. */
}
.foo .qux {
  /* .. */
}
.foo .qux .quz {
  /* .. */
}

Again, my reasons are totally subjective and I don't think that the feature itself is bad —to be really honest I don't find it useful since I tend to "nest" in very rare occasions— rather that it could be easily abused and misused —at least in my experience.

Hope this adds to the conversation. 😀

@LeaVerou

This comment has been minimized.

Show comment
Hide comment
@LeaVerou

LeaVerou Jun 14, 2018

Contributor

@battaglr In my opinion neither of your code examples are inherently bad. It all depends on what .foo, .bar etc actually mean, i.e. what is the actual intent behind each selector. If nesting expresses the intent correctly, then nesting is perfectly appropriate.

Contributor

LeaVerou commented Jun 14, 2018

@battaglr In my opinion neither of your code examples are inherently bad. It all depends on what .foo, .bar etc actually mean, i.e. what is the actual intent behind each selector. If nesting expresses the intent correctly, then nesting is perfectly appropriate.

@battaglr

This comment has been minimized.

Show comment
Hide comment
@battaglr

battaglr Jun 14, 2018

@LeaVerou, we agree on that: those selectors are not inherently bad. I assumed that it was clear that nesting wasn't necessary in those examples, but clearly it wasn't. Thanks for pointing that out.

@LeaVerou, we agree on that: those selectors are not inherently bad. I assumed that it was clear that nesting wasn't necessary in those examples, but clearly it wasn't. Thanks for pointing that out.

@chriseppstein

This comment has been minimized.

Show comment
Hide comment
@chriseppstein

chriseppstein Jun 15, 2018

This is a place where preprocessors can still add value.

I want powerful and full-featured native nesting, without using any kind of preprocessor.

@tobireif So do I. But there are some trade-offs to be made when bringing features to the browser and parsing selectors with a finite lookahead is one of them. I was just pointing out that pre-processors can make the authored source code slightly cleaner for those teams who choose to adopt one.

This is a place where preprocessors can still add value.

I want powerful and full-featured native nesting, without using any kind of preprocessor.

@tobireif So do I. But there are some trade-offs to be made when bringing features to the browser and parsing selectors with a finite lookahead is one of them. I was just pointing out that pre-processors can make the authored source code slightly cleaner for those teams who choose to adopt one.

@jonjohnjohnson

This comment has been minimized.

Show comment
Hide comment
@jonjohnjohnson

jonjohnjohnson Jun 15, 2018

@tobireif @chriseppstein All I can say is if native nesting was spec'd in a way where many of my projects time to first render was significantly slower, for the reason of developer convenience, I'd just end up using a preprocessor for nesting, not risking perf hits for my users.

@tobireif @chriseppstein All I can say is if native nesting was spec'd in a way where many of my projects time to first render was significantly slower, for the reason of developer convenience, I'd just end up using a preprocessor for nesting, not risking perf hits for my users.

@chriseppstein

This comment has been minimized.

Show comment
Hide comment
@chriseppstein

chriseppstein Jun 15, 2018

@jonjohnjohnson As I understand it, it's not that it's a performance hit per se, it's just that none of the css parsers are built to handle arbitrary token look-aheads. So a spec that requires such a thing will get rejected.

In terms of performance, it will be interesting to benchmark the relative performance of precomputed nesting with compression vs an in-browser expansion with compression. The compression algorithms used by gzip and brotli do a good job with compressing duplicate idents in close proximity -- exactly the type that nesting produces, so precomputed nesting may turn out to be a performance benefit due to having only negligible impact on stylesheet transfer time after compression.

@jonjohnjohnson As I understand it, it's not that it's a performance hit per se, it's just that none of the css parsers are built to handle arbitrary token look-aheads. So a spec that requires such a thing will get rejected.

In terms of performance, it will be interesting to benchmark the relative performance of precomputed nesting with compression vs an in-browser expansion with compression. The compression algorithms used by gzip and brotli do a good job with compressing duplicate idents in close proximity -- exactly the type that nesting produces, so precomputed nesting may turn out to be a performance benefit due to having only negligible impact on stylesheet transfer time after compression.

@tobireif

This comment has been minimized.

Show comment
Hide comment
@tobireif

tobireif Jun 16, 2018

The spec writers keep perf in mind, the implementers keep perf in mind, I can't imagine native nesting having any perf impact that's noticeable/relevant for the user (except perhaps for very extreme stylesheets).

Since all mentions of perf in this thread are speculative, the actual performance (per browser and with different types of nesting usage) remains to be measured ...

The spec writers keep perf in mind, the implementers keep perf in mind, I can't imagine native nesting having any perf impact that's noticeable/relevant for the user (except perhaps for very extreme stylesheets).

Since all mentions of perf in this thread are speculative, the actual performance (per browser and with different types of nesting usage) remains to be measured ...

@jonathantneal

This comment has been minimized.

Show comment
Hide comment
@jonathantneal

jonathantneal Jun 21, 2018

Contributor

Undecided as of yet! Don't get too excited until we get a real decision next week.
@tabatkins

Well, people not paying attention in the closing minutes were put on notice. So it is almost real now.
@svgeesus

We didn't get to the topic! We'll discuss it at f2f in two weeks, I think.
@tabatkins

Given the interest last round, is there an agenda label or email or something needed so that this doesn’t slip away?

Contributor

jonathantneal commented Jun 21, 2018

Undecided as of yet! Don't get too excited until we get a real decision next week.
@tabatkins

Well, people not paying attention in the closing minutes were put on notice. So it is almost real now.
@svgeesus

We didn't get to the topic! We'll discuss it at f2f in two weeks, I think.
@tabatkins

Given the interest last round, is there an agenda label or email or something needed so that this doesn’t slip away?

@lahmatiy

This comment has been minimized.

Show comment
Hide comment
@lahmatiy

lahmatiy Jun 29, 2018

Contributor

One issue is missed in this thread – error handling. According to spec declarations and qualified rules (nested rules as well) have different rules for bad content elimination.
For example, the CSS:

.example {
  background: white;
  &:hover {
     background: gray;
     color: green;
  }
  color: red;
}

Will turn to for any modern browser:

.example {
  background: white;
}

So color: red will be vanished as a bad content.
However, with nesting rule support things may be changed – color: red will be applied, even with an error in selector (that produce a bad qualified rule that will be thrown away). Probably declarations after a nested rules will be prohibited, it can compensate the difference a little (declarations after a declaration closest to nested rule ending will be applied by modern browsers anyway).
I believe, nobody is used & in CSS today. So introducing & as a starting for a nested qualified rule is quite safe.

Alternatively, the only ambiguous case is when the selector starts with an element selector, right? If it starts with an id, class, pseudo-class, or pseudo-element, we know immediately.
What if the ampersand was only required in that case?

We need to remember about browser's hacks. Many symbols could used for addressing styles for IE6-7 only. Some of them are valid as a starting for a selector:

.selector { &property: value; } /* only if nested rules will be supported */
.selector { *property: value; }
.selector { .property: value; }
.selector { #property: value; }
.selector { :property: value; }

When IE6-7 were actual, a star hack was quite popular. According to my research this hack is still preset on many sites:

  • * hack is present at least on 79 sites of Alexa Top 250 (3192 occurrences)
  • # hack is present at least on 3 sites of Alexa Top 250 (54 occurrences)

So, if spec will allow to start a nested rule with any of those characters, many sites can be broken. Because different amount of content will be thrown away (by modern browsers and browsers with such support).

From this standpoint, the restriction to start a nested rule only with & is quite fair. But it's still unclear what other side effects it can introduce in parsing of modern and old web CSS.

Contributor

lahmatiy commented Jun 29, 2018

One issue is missed in this thread – error handling. According to spec declarations and qualified rules (nested rules as well) have different rules for bad content elimination.
For example, the CSS:

.example {
  background: white;
  &:hover {
     background: gray;
     color: green;
  }
  color: red;
}

Will turn to for any modern browser:

.example {
  background: white;
}

So color: red will be vanished as a bad content.
However, with nesting rule support things may be changed – color: red will be applied, even with an error in selector (that produce a bad qualified rule that will be thrown away). Probably declarations after a nested rules will be prohibited, it can compensate the difference a little (declarations after a declaration closest to nested rule ending will be applied by modern browsers anyway).
I believe, nobody is used & in CSS today. So introducing & as a starting for a nested qualified rule is quite safe.

Alternatively, the only ambiguous case is when the selector starts with an element selector, right? If it starts with an id, class, pseudo-class, or pseudo-element, we know immediately.
What if the ampersand was only required in that case?

We need to remember about browser's hacks. Many symbols could used for addressing styles for IE6-7 only. Some of them are valid as a starting for a selector:

.selector { &property: value; } /* only if nested rules will be supported */
.selector { *property: value; }
.selector { .property: value; }
.selector { #property: value; }
.selector { :property: value; }

When IE6-7 were actual, a star hack was quite popular. According to my research this hack is still preset on many sites:

  • * hack is present at least on 79 sites of Alexa Top 250 (3192 occurrences)
  • # hack is present at least on 3 sites of Alexa Top 250 (54 occurrences)

So, if spec will allow to start a nested rule with any of those characters, many sites can be broken. Because different amount of content will be thrown away (by modern browsers and browsers with such support).

From this standpoint, the restriction to start a nested rule only with & is quite fair. But it's still unclear what other side effects it can introduce in parsing of modern and old web CSS.

@css-meeting-bot

This comment has been minimized.

Show comment
Hide comment
@css-meeting-bot

css-meeting-bot Jul 4, 2018

Member

The Working Group just discussed css nesting, and agreed to the following:

  • RESOLVED: add css-nesting as an ED, Tab Atkins as editor, file issues until ppl are overall kinda happy with what it's like before we consider FPWD
The full IRC log of that discussion <florian> topic: css nesting
<florian> github: https://github.com/w3c/csswg-drafts/issues/2701
<florian> TabAtkins: we tried to discuss that a while back, but didn't have time to conclude. Should we rediscuss, or re-resolve
<TabAtkins> https://tabatkins.github.io/specs/css-nesting/
<florian> myles: I want an overview
<florian> TabAtkins: nesting style rules is a common request, and a feature of every css preporsessor in existence
<florian> TabAtkins: and one of their most popular feature
<florian> TabAtkins: makes stylesheets much easier to maintain
<florian> TabAtkins: it is purely syntatic sugar, but is worth covering because of the huge demand
<florian> TabAtkins: the way they're done in preprocessors are ambiguous with properties
<florian> TabAtkins: My propose spec disambiguate with by using &
<florian> TabAtkins: you can use & at the front, and if you want it elsewhere, you can use @nest to keep things unambiguous
<TabAtkins> a:hover ....
<florian> TabAtkins: the above looks like a "a" property with a "hover" value
<frremy> q+
<florian> TabAtkins: CSS parsing only requires a finite amount of lookahead, and we'd like to keep it that way
<florian> leaverou: isn't it only a problem when the tag selector is the first part of the selector
<florian> TabAtkins: I don't like that because it's not obvious, and hard to teach
<Rossen> q?
<florian> fantasai: you could pick a random character to start any rule with
<astearns> ack frremy
<fantasai> s/any/every/
<florian> TabAtkins: yes, that's what "@nest" do
<florian> frremy: replace @nest with &
<TabAtkins> & &.foo {...}{
<florian> TabAtkins: it's ambiguous
<heycam> q+
<florian> Florian: I don't like it, @nest is nicer
<florian> leaverou: that would be hard to read
<frremy> &:hover
<frremy> & > span > &
<florian> frremy: you only include it if needed
<TabAtkins> & span:not(&) {...}
<Rossen> q?
<florian> TabAtkins: other bad example ^
<astearns> ack heycam
<myles> Q+
<frremy> (I was convinced by the clarification that the & can be replaced more than one in the selector , which I didn't know)
<myles> -q
<florian> heycam: can we require starting with a combinator (and use an explicit descendant combinator)
<florian> TabAtkins: doesn't solve it for & in the middle
<florian> fantasai: if you use @nest, use it everywhere
<florian> TabAtkins: too verbose
<florian> heycam: @nest introduces a block?
<florian> leaverou: ????
<fantasai> s/everywhere/everywhere. If you think that's too verbose, choose a different disambiguator. Alternating between using @nest and not is not great/
<florian> TabAtkins: very hard to express in grammars
<florian> TabAtkins: in the most common cases, stating with an ampersand is short, which is important
<florian> fantasai: just use something shorter than @nest
<fantasai> s/just//
<florian> Florian, fantasai: how about naked @
<florian> myles: we don't have to bikeshed the syntax if we're just talking about adopting the module
<leaverou> fantasai: or naked & to introduce a nested block? /* just throwing ideas! */
<florian> astearns: objections?
<fantasai> s/fantasai:/fantasai,/
<florian> frremy: does it need to be a new module?
<florian> florian: no, but it's nice that way
<florian> astearns: objections?
<florian> fantasai: ED is fine, want to bikeshed the syntax before FPWD
<fantasai> fantasai: Seems like nobody is really happy with the spec as-i
<fantasai> s/as-i/as-is/
<florian> xidorn: no objection, but my concern is that it expands in some cases into :matches() like things
<florian> xidorn: and that's hard to optimize
<florian> TabAtkins: you can expand them out fully
<florian> emilio: how about the OM?
<florian> TabAtkins: not expanded in the OM
<florian> xidorn: that makes it hard
<fantasai> s/in the OM/in the OM, rules get a .childRules object/
<florian> xidorn: because of the combinatorial explosion
<florian> florian: we still have to deal with that in preprocessor generated sylesheets
<fantasai> ScribeNick: fantasai
<fantasai> astearns: Hearing no objections to starting work on the module. Hearing a lot of issues against it.
<fantasai> astearns: Anyone else interested in heping Tab?
<fantasai> RESOLVED: add css-nesting as an ED, Tab Atkins as editor, file issues until ppl are overall kinda happy with what it's like before we consider FPWD
Member

css-meeting-bot commented Jul 4, 2018

The Working Group just discussed css nesting, and agreed to the following:

  • RESOLVED: add css-nesting as an ED, Tab Atkins as editor, file issues until ppl are overall kinda happy with what it's like before we consider FPWD
The full IRC log of that discussion <florian> topic: css nesting
<florian> github: https://github.com/w3c/csswg-drafts/issues/2701
<florian> TabAtkins: we tried to discuss that a while back, but didn't have time to conclude. Should we rediscuss, or re-resolve
<TabAtkins> https://tabatkins.github.io/specs/css-nesting/
<florian> myles: I want an overview
<florian> TabAtkins: nesting style rules is a common request, and a feature of every css preporsessor in existence
<florian> TabAtkins: and one of their most popular feature
<florian> TabAtkins: makes stylesheets much easier to maintain
<florian> TabAtkins: it is purely syntatic sugar, but is worth covering because of the huge demand
<florian> TabAtkins: the way they're done in preprocessors are ambiguous with properties
<florian> TabAtkins: My propose spec disambiguate with by using &
<florian> TabAtkins: you can use & at the front, and if you want it elsewhere, you can use @nest to keep things unambiguous
<TabAtkins> a:hover ....
<florian> TabAtkins: the above looks like a "a" property with a "hover" value
<frremy> q+
<florian> TabAtkins: CSS parsing only requires a finite amount of lookahead, and we'd like to keep it that way
<florian> leaverou: isn't it only a problem when the tag selector is the first part of the selector
<florian> TabAtkins: I don't like that because it's not obvious, and hard to teach
<Rossen> q?
<florian> fantasai: you could pick a random character to start any rule with
<astearns> ack frremy
<fantasai> s/any/every/
<florian> TabAtkins: yes, that's what "@nest" do
<florian> frremy: replace @nest with &
<TabAtkins> & &.foo {...}{
<florian> TabAtkins: it's ambiguous
<heycam> q+
<florian> Florian: I don't like it, @nest is nicer
<florian> leaverou: that would be hard to read
<frremy> &:hover
<frremy> & > span > &
<florian> frremy: you only include it if needed
<TabAtkins> & span:not(&) {...}
<Rossen> q?
<florian> TabAtkins: other bad example ^
<astearns> ack heycam
<myles> Q+
<frremy> (I was convinced by the clarification that the & can be replaced more than one in the selector , which I didn't know)
<myles> -q
<florian> heycam: can we require starting with a combinator (and use an explicit descendant combinator)
<florian> TabAtkins: doesn't solve it for & in the middle
<florian> fantasai: if you use @nest, use it everywhere
<florian> TabAtkins: too verbose
<florian> heycam: @nest introduces a block?
<florian> leaverou: ????
<fantasai> s/everywhere/everywhere. If you think that's too verbose, choose a different disambiguator. Alternating between using @nest and not is not great/
<florian> TabAtkins: very hard to express in grammars
<florian> TabAtkins: in the most common cases, stating with an ampersand is short, which is important
<florian> fantasai: just use something shorter than @nest
<fantasai> s/just//
<florian> Florian, fantasai: how about naked @
<florian> myles: we don't have to bikeshed the syntax if we're just talking about adopting the module
<leaverou> fantasai: or naked & to introduce a nested block? /* just throwing ideas! */
<florian> astearns: objections?
<fantasai> s/fantasai:/fantasai,/
<florian> frremy: does it need to be a new module?
<florian> florian: no, but it's nice that way
<florian> astearns: objections?
<florian> fantasai: ED is fine, want to bikeshed the syntax before FPWD
<fantasai> fantasai: Seems like nobody is really happy with the spec as-i
<fantasai> s/as-i/as-is/
<florian> xidorn: no objection, but my concern is that it expands in some cases into :matches() like things
<florian> xidorn: and that's hard to optimize
<florian> TabAtkins: you can expand them out fully
<florian> emilio: how about the OM?
<florian> TabAtkins: not expanded in the OM
<florian> xidorn: that makes it hard
<fantasai> s/in the OM/in the OM, rules get a .childRules object/
<florian> xidorn: because of the combinatorial explosion
<florian> florian: we still have to deal with that in preprocessor generated sylesheets
<fantasai> ScribeNick: fantasai
<fantasai> astearns: Hearing no objections to starting work on the module. Hearing a lot of issues against it.
<fantasai> astearns: Anyone else interested in heping Tab?
<fantasai> RESOLVED: add css-nesting as an ED, Tab Atkins as editor, file issues until ppl are overall kinda happy with what it's like before we consider FPWD

@astearns astearns removed the Agenda+ F2F label Jul 4, 2018

@kizu

This comment has been minimized.

Show comment
Hide comment
@kizu

kizu Jul 4, 2018

@lahmatiy re: error handling, it would be very easy to ensure that the declarations after the nesting won't be affected by the nesting support: use semicolon after the nesting, see this example: https://codepen.io/kizu/pen/dKLQJR

kizu commented Jul 4, 2018

@lahmatiy re: error handling, it would be very easy to ensure that the declarations after the nesting won't be affected by the nesting support: use semicolon after the nesting, see this example: https://codepen.io/kizu/pen/dKLQJR

@tobireif

This comment has been minimized.

Show comment
Hide comment
@tobireif

tobireif Jul 5, 2018

The Working Group just discussed css nesting, and agreed to the following:

RESOLVED: add css-nesting as an ED, Tab Atkins as editor, file issues until ppl are overall kinda happy with what it's like before we consider FPWD

Wow! Native CSS Nesting is coming!

I'm sure I'm echoing what many web devs feel:

Thank you CSS WG!

tobireif commented Jul 5, 2018

The Working Group just discussed css nesting, and agreed to the following:

RESOLVED: add css-nesting as an ED, Tab Atkins as editor, file issues until ppl are overall kinda happy with what it's like before we consider FPWD

Wow! Native CSS Nesting is coming!

I'm sure I'm echoing what many web devs feel:

Thank you CSS WG!

@tobireif

This comment has been minimized.

Show comment
Hide comment
@tobireif

tobireif Jul 5, 2018

This ticket here could get added to https://tabatkins.github.io/specs/css-nesting/ as issue, under "Issues Index", because many concerns were raised in this here ticket.

tobireif commented Jul 5, 2018

This ticket here could get added to https://tabatkins.github.io/specs/css-nesting/ as issue, under "Issues Index", because many concerns were raised in this here ticket.

@isellsoap

This comment has been minimized.

Show comment
Hide comment
@isellsoap

isellsoap Jul 5, 2018

I’m actually quite surprised to read so few comments pointing out the danger of misuse of this feature. Heck, what am I saying: it is a feature that will get misused for sure. Thanks to @battaglr for pointing out the issues in your comments here.

It is my personal experience looking back at 5 years of professional work in web development, having seen and worked with really big Sass/Less architectures from very popular German websites, that the nesting of selectors is one of the main reasons why the resulting CSS is a maintainability nightmare.

I, of course, see also the benefits of the feature. But the reality is that you have a diverse pool of people working on stylesheets (especially when we are talking about big teams) and the misuses (which are, again, kindly elaborated by @battaglr in his comments here) are predestined, in my point of view.

isellsoap commented Jul 5, 2018

I’m actually quite surprised to read so few comments pointing out the danger of misuse of this feature. Heck, what am I saying: it is a feature that will get misused for sure. Thanks to @battaglr for pointing out the issues in your comments here.

It is my personal experience looking back at 5 years of professional work in web development, having seen and worked with really big Sass/Less architectures from very popular German websites, that the nesting of selectors is one of the main reasons why the resulting CSS is a maintainability nightmare.

I, of course, see also the benefits of the feature. But the reality is that you have a diverse pool of people working on stylesheets (especially when we are talking about big teams) and the misuses (which are, again, kindly elaborated by @battaglr in his comments here) are predestined, in my point of view.

@chriscoyier

This comment has been minimized.

Show comment
Hide comment
@chriscoyier

chriscoyier Jul 5, 2018

it is a feature that will get misused for sure.

<div class="polka-dots fontLarge blue new-blue border--radius___L">
  <p style="font-family: "Comic Sans MS;">What.</p>
</div>

(Literally any feature of any language can be mis-used, right?)

it is a feature that will get misused for sure.

<div class="polka-dots fontLarge blue new-blue border--radius___L">
  <p style="font-family: "Comic Sans MS;">What.</p>
</div>

(Literally any feature of any language can be mis-used, right?)

@battaglr

This comment has been minimized.

Show comment
Hide comment
@battaglr

battaglr Jul 5, 2018

@chriscoyier,

Literally any feature of any language can be mis-used, right?

You're totally right, and I agree. 😀👍

What I think is important about the "potential disadvantages" that some pointed out it's that maybe we could use them to improve (if it's possible) this feature to discourage them —not sure how that could be possible.

battaglr commented Jul 5, 2018

@chriscoyier,

Literally any feature of any language can be mis-used, right?

You're totally right, and I agree. 😀👍

What I think is important about the "potential disadvantages" that some pointed out it's that maybe we could use them to improve (if it's possible) this feature to discourage them —not sure how that could be possible.

@tobireif

This comment has been minimized.

Show comment
Hide comment
@tobireif

tobireif Jul 5, 2018

Perhaps allow only one level of nesting? Probably too draconian ...

tobireif commented Jul 5, 2018

Perhaps allow only one level of nesting? Probably too draconian ...

@LeaVerou

This comment has been minimized.

Show comment
Hide comment
@LeaVerou

LeaVerou Jul 6, 2018

Contributor

@isellsoap A lot of the "misuse" of existing nesting is based on the fact that it's compiled down to non-nested CSS. These issues go away if nesting is supported natively and never has to be flattened.
Also, I'm not a huge fan of the type of argumentation that is basically "listen to me, I have experience and I'm telling you, this is a bad thing". Appeal to authority is not how we work. You have to list specific issues. If @battaglr did that for you, then what does your comment add that a 👍on his comment wouldn’t?

Contributor

LeaVerou commented Jul 6, 2018

@isellsoap A lot of the "misuse" of existing nesting is based on the fact that it's compiled down to non-nested CSS. These issues go away if nesting is supported natively and never has to be flattened.
Also, I'm not a huge fan of the type of argumentation that is basically "listen to me, I have experience and I'm telling you, this is a bad thing". Appeal to authority is not how we work. You have to list specific issues. If @battaglr did that for you, then what does your comment add that a 👍on his comment wouldn’t?

@isellsoap

This comment has been minimized.

Show comment
Hide comment
@isellsoap

isellsoap Jul 6, 2018

@LeaVerou

A lot of the "misuse" of existing nesting is based on the fact that it's compiled down to non-nested CSS. These issues go away if nesting is supported natively and never has to be flattened.

But the specificity of nested selectors, in the end, is the same, isn’t it?

So

.a {
  & .b {}
}

is the same as writing

.a .b {}

At least I hope I understood native CSS nesting correctly here. For me this means that the nesting obfuscates the specificity by a lot. With compiled and flattened CSS selectors (if we were to use Sass nesting), at least in the end I can look at what the browser actually has to deal with. It’s more explicit that way. I’m not sure if I can get across what I actually mean. 🤔

Appeal to authority is not how we work.

I know and I certainly didn’t intend to generate that impression with my comment.

isellsoap commented Jul 6, 2018

@LeaVerou

A lot of the "misuse" of existing nesting is based on the fact that it's compiled down to non-nested CSS. These issues go away if nesting is supported natively and never has to be flattened.

But the specificity of nested selectors, in the end, is the same, isn’t it?

So

.a {
  & .b {}
}

is the same as writing

.a .b {}

At least I hope I understood native CSS nesting correctly here. For me this means that the nesting obfuscates the specificity by a lot. With compiled and flattened CSS selectors (if we were to use Sass nesting), at least in the end I can look at what the browser actually has to deal with. It’s more explicit that way. I’m not sure if I can get across what I actually mean. 🤔

Appeal to authority is not how we work.

I know and I certainly didn’t intend to generate that impression with my comment.

@battaglr

This comment has been minimized.

Show comment
Hide comment
@battaglr

battaglr Jul 6, 2018

@tobireif,

Perhaps allow only one level of nesting? Probably too draconian ...

Yeap, my only idea was to limitate the level of nesting... but doesn't make sense to add a feature with arbitrary limitations like that. Linters will cover that, as they are doing today.


Despite my initial rejection to the idea of adding native support for nesting, I realize that the issues I mention in previous comments would be a problem if (1) you agree that "flat" specificity is a good thing and (2) you work in long-lived and or large codebases where many people with different levels of experience add code; in short-lived —or those that don't require much change— or small codebases I don't thing that nesting would be an issue —at least that's my experience.

battaglr commented Jul 6, 2018

@tobireif,

Perhaps allow only one level of nesting? Probably too draconian ...

Yeap, my only idea was to limitate the level of nesting... but doesn't make sense to add a feature with arbitrary limitations like that. Linters will cover that, as they are doing today.


Despite my initial rejection to the idea of adding native support for nesting, I realize that the issues I mention in previous comments would be a problem if (1) you agree that "flat" specificity is a good thing and (2) you work in long-lived and or large codebases where many people with different levels of experience add code; in short-lived —or those that don't require much change— or small codebases I don't thing that nesting would be an issue —at least that's my experience.

@jonathantneal

This comment has been minimized.

Show comment
Hide comment
@jonathantneal

jonathantneal Jul 6, 2018

Contributor

Thanks for fulfilling this request! I will be closing this issue.

Here is a PR to add this spec to the repository: #2878.

For those interested, here are new issues capturing further discussion of css nesting:

  • How should invalid nesting rules be handled: #2880.
  • A concern about combinatorial explosion: #2881.
  • Add support for at-rules: #2891.
Contributor

jonathantneal commented Jul 6, 2018

Thanks for fulfilling this request! I will be closing this issue.

Here is a PR to add this spec to the repository: #2878.

For those interested, here are new issues capturing further discussion of css nesting:

  • How should invalid nesting rules be handled: #2880.
  • A concern about combinatorial explosion: #2881.
  • Add support for at-rules: #2891.
@Nodws

This comment has been minimized.

Show comment
Hide comment
@Nodws

Nodws Jul 9, 2018

That's cool and all but we want a parent selector.
.child < div { }

Nodws commented Jul 9, 2018

That's cool and all but we want a parent selector.
.child < div { }

@tomhodgins

This comment has been minimized.

Show comment
Hide comment
@tomhodgins

tomhodgins Jul 9, 2018

That's cool and all but we want a parent selector.

This might be off-topic for this issue about selector nesting.

Could your desired selector .child < div be expressed as div:has(.child) according to how :has() is being specced? If what you want it isn't yet covered by what :has() is specced to do, it would probably be better to open a new issue to discuss this than to comment in this closed issue :)

That's cool and all but we want a parent selector.

This might be off-topic for this issue about selector nesting.

Could your desired selector .child < div be expressed as div:has(.child) according to how :has() is being specced? If what you want it isn't yet covered by what :has() is specced to do, it would probably be better to open a new issue to discuss this than to comment in this closed issue :)

@tobireif

This comment has been minimized.

Show comment
Hide comment
@tobireif

tobireif Jul 9, 2018

That's cool and all but we want a parent selector.

You could file a new ticket at https://github.com/w3c/csswg-drafts/issues/new .

tobireif commented Jul 9, 2018

That's cool and all but we want a parent selector.

You could file a new ticket at https://github.com/w3c/csswg-drafts/issues/new .

@matthew-dean

This comment has been minimized.

Show comment
Hide comment
@matthew-dean

matthew-dean Jul 16, 2018

I worry that the use of & in the proposal is going to lead to a lot of confusion, since it doesn't work like Sass's / Less's &. So half your code may need to be flattened, and half can maybe preserve &. When writing in Sass or Less, how do you target which is which? The preprocessing languages don't lose all usefulness, so both of these ecosystems, if this were adopted, would have to re-invent their entire & syntax / usage if people want to target nested selectors as output. Which is a shame, because that would slow adoption and probably lead more to reject using this feature.

I don't have a better syntax suggestion, but I also don't see this as necessary. But, obviously as a Less contributor, I'm biased.

Most "best-practice" style-writing I've seen suggests not really nesting at all, but to use single class identifiers in a BEM-way, like:

.component {
  &--header { }
  &--body {}
  &--button {
    &:hover {} //etc
  }
}

This keeps things organized and provides single class matching for the browser. I do get why adopting that form (partial class appending) would be rejected by a CSS spec, because CSS is looking to define complete selector matching, but that just points to a preprocessor still being relevant, which points to a potential conflict around & usage and output. I think a different syntax is needed.

I worry that the use of & in the proposal is going to lead to a lot of confusion, since it doesn't work like Sass's / Less's &. So half your code may need to be flattened, and half can maybe preserve &. When writing in Sass or Less, how do you target which is which? The preprocessing languages don't lose all usefulness, so both of these ecosystems, if this were adopted, would have to re-invent their entire & syntax / usage if people want to target nested selectors as output. Which is a shame, because that would slow adoption and probably lead more to reject using this feature.

I don't have a better syntax suggestion, but I also don't see this as necessary. But, obviously as a Less contributor, I'm biased.

Most "best-practice" style-writing I've seen suggests not really nesting at all, but to use single class identifiers in a BEM-way, like:

.component {
  &--header { }
  &--body {}
  &--button {
    &:hover {} //etc
  }
}

This keeps things organized and provides single class matching for the browser. I do get why adopting that form (partial class appending) would be rejected by a CSS spec, because CSS is looking to define complete selector matching, but that just points to a preprocessor still being relevant, which points to a potential conflict around & usage and output. I think a different syntax is needed.

@AmeliaBR

This comment has been minimized.

Show comment
Hide comment
@AmeliaBR

AmeliaBR Jul 16, 2018

@matthew-dean That's a really good point, but this is a closed issue. Could you file a new issue, starting the subject line with [css-nesting]?

@matthew-dean That's a really good point, but this is a closed issue. Could you file a new issue, starting the subject line with [css-nesting]?

@exdeniz

This comment has been minimized.

Show comment
Hide comment
@exdeniz

exdeniz Jul 18, 2018

Add @media to draft. Like this

.foo {
  color: red;
  @media (min-width: 20rem) {
    color: blue;
    @media (max-width: 30rem) {
      color: green;
    }
  }
}

exdeniz commented Jul 18, 2018

Add @media to draft. Like this

.foo {
  color: red;
  @media (min-width: 20rem) {
    color: blue;
    @media (max-width: 30rem) {
      color: green;
    }
  }
}
@Garbee

This comment has been minimized.

Show comment
Hide comment
@Garbee

Garbee Jul 18, 2018

@exdeniz The comment that closed this issue has @rule support listed as one of the issues to be addressed already. So they have been aware of this desire and it will be looked into with specifying and implementing this behavior.

Garbee commented Jul 18, 2018

@exdeniz The comment that closed this issue has @rule support listed as one of the issues to be addressed already. So they have been aware of this desire and it will be looked into with specifying and implementing this behavior.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment