-
Notifications
You must be signed in to change notification settings - Fork 689
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[css-nesting-1] Yet another nesting proposal (Option 5) #7970
Comments
I like the cleanness of this proposal, but I think it can be a bit annoying when you start styling an element... foo {
color: blue;
} and then realize you also want to style the descendants, so you have to refactor it all. With other proposals the change is simpler:
|
I think the refactoring is fairly minimal, you're just prepending I do have to note that your example is slightly wrong: +@nest foo {
+ & {
+ color: blue;
+ }
+ & bar {
+ color: red;
+ }
+} but: +@nest foo {
+ & {
+ color: blue;
+ }
+ bar {
+ color: red;
+ }
+} (note no The basic gist is that instead of a style rule that expects properties, we're minting a new kind of style rule that expects nested selectors. And then providing a carve-out for properties. |
Just noting it's still a less local change, since probably the cursor is at the end of the declarations, and then you have to go back to the selector, select all the declarations to indent them, etc. Not a big problem but it's an annoyance for me.
Even if optional, I hope |
No, not on a nested rule. The As I said, by default, everything inside a My original thought was to not even allow properties inside at all, e.g.:
but having to repeat the first selector seemed an unnecessary redundancy. The main issue with all the other proposals is that style rules expect properties, and the syntax for properties has way too many collisions with selectors, so a carve-out for allowing selectors gets cumbersome. This proposal makes a new kind of style rule that expects nested style rules, the carve-out is to allow properties within a limited scope. Another detail that I didn't mention originally, by default there's an ancestor combinator between the E.g.:
would be equivalent to:
and
would be equivalent to:
|
Why disallow @nest foo {
&:hover { color: blue; }
bar + & { color: red }
& + & { color: green }
} |
Note: it has one collision with selectors. The carve-out to avoid the ambiguity is rather simple, as Option 3 has shown.
It must be allowed, to hit a number of important use-cases, namely the But yeah, generally I agree with Oriol. This is a relatively invasive change to add nesting to an existing style rule. It continues to require non-local edits in deeper nesting, too, going from: @nest foo {
bar {color: red;}
} to @nest foo {
@nest bar {
& { color: red; }
baz { color: green; }
}
} |
Ok, in my original thinking So we can allow the I disagree with the added indenting being a problem however, all modern code editors can indent and un-indent blocks with a single keystroke, and any decent diff tool will also clearly show changes as being whitespace-only. I don't see this a burden on developers (in fact, showing that something is now the root of a nesting context in a diff may actually be useful). I still think this proposal deserves consideration as it neatly side-steps all the other issues with the other nesting proposals. |
I agree with Tab here. Having to jump around in your code upon pasting a block to enable nesting does not seem feasible to me (-). Only benefit I see this approach has over proposal 4, is that this one actually can nest the nested stuff (+), but that also requires a code adjustment in which you need to put the declarations in a nested (Note: proposals 3 and 1 still have my preference, as indicated in the voting round we did here). |
The CSS Working Group just discussed
The full IRC log of that discussion<jensimmons> I'd like to begin this discussion by requesting we call this "Option 5".<fantasai> RESOLVED: call this Option 5 :) <fantasai> plinss: This is something I've been wanting to do since the 90s, and immediately ran into problem of conflicts when nesting selectors inside a rule that expects properties <fantasai> plinss: I understand option 3 is trying to find workaround, an doption 4 a different approach <fantasai> plinss: Wondering what if we turn the problem around entirely <fantasai> plinss: and introduce a top-level construct that only contains nested rules <fantasai> plinss: so never mix properties and rules in a single context <fantasai> plinss: My concern with Option 3 is that even if we have a syntactic way to disambiguous, that does paint us into a corner <fantasai> plinss: harder to introduce new things in the future <fantasai> plinss: My proposal is to introduce an @rule, calling @nest <fantasai> plinss: and inside that block is nothing but nested rules <fantasai> plinss: Can have no selector for a block, and that applies properties to the top-level selector <TabAtkins> q+ <fantasai> plinss: No parsing changes, no extra lookahead, no changes to OM, easy to explain, no special bizarre syntax rules, just works <fantasai> plinss: Downside is you add an extra layer of indenting for properties that apply to top-level rule <fantasai> plinss: but I don't see that as a problem because I add extra blocks to code all the time, modern tools make this easy <fantasai> plinss: it's easy to see what happens <oriol> q+ <fantasai> plinss: I think this is much better than adding cognitive load to authors, learning weird parsing exception rules <fremy> q? <Rossen_> ack TabAtkins <oriol> q- <fantasai> TabAtkins: As I said in issue, my objection is still that it requires a non-local edit <fantasai> TabAtkins: Can't just add stuff, need to go back and change the existing rule to allow nesting <fantasai> TabAtkins: It's a non-trivial bit of work, and is distinct from the way that every preprocessor has tried to do things since they invented nesting <fantasai> TabAtkins: Also, I continue to think that any statement about complexity of the rules for Option 3 is overstated, it's literally just "does the selector start with an identifier? if so need a prefix" <fremy> q+ <fantasai> TabAtkins: not that big a deal to learn or work around <fantasai> TabAtkins: Doing non-local edits to add nested rules to something is also a cognitive load when making edits in place <fantasai> TabAtkins: I don't like it <fantasai> TabAtkins: it does have better qualities than some other proposals <fantasai> TabAtkins: but it's roughly equivalent to just prepending @nest to all rules in terms of overall functionality, just changes where @nest shows up basically <fantasai> TabAtkins: That's been mildly rejected by authors and WG already, would like to avoid <fantasai> plinss: On the conflict issue, the point that you're missing is that mixing selectors and properties in one block does constrain us for future expansion <fantasai> plinss: if we ever want to put [missed] in a property block, we can't do that <fantasai> plinss: I'm very concerned about contraining our ability to expand CSS later <fantasai> TabAtkins: I share your concern. Still have some room for expansion, so I'm okay with it. E.g. if your expansion is after property name, can still do that; or if we introduce functional notations, we can still do that <fantasai> TabAtkins: neither of these would be parsed as a nested rule <fantasai> TabAtkins: so think there's still enough space for expansion, in my opinion <ydaniv> s/contraining/constraining/ <fantasai> plinss: Also, you can interleave properties and nested rules, how does that show up in the OM? Will lose that on reserialization <fantasai> plinss: my proposal avoids because can't do that <fantasai> TabAtkins: Assigning meaning to ordering seems fraught in first place, but it does mean when reserialize it'll look different from input <Rossen_> q <fantasai> plinss: no functional difference, but authors will order things for organizational reasons, and it's a loss to the author if lost on reserializatoin <astearns> In option 5 you can still interleave, I think `@nest foo { & {} bar {} & {} }` <fantasai> fremy: I feel like there's a way of serializing this <fantasai> fremy: I don't agree that if you allow properties after rules it's meaningless <fantasai> fremy: it's same as selector with & only <fantasai> fremy: It affects ordering <fantasai> fremy: If your property defined after a rule doesn't work <fantasai> fremy: but that's a different topic, but it's something to consider <plinss> astearns, yes, but the ordering is preserved because they're all style rules <astearns> ok <fantasai> fremy: Other than that, I feel like one positive point from plinss's proposal he didn't mention <fantasai> fremy: Shared with Option 4 <fantasai> fremy: It's ability to copy / paste <fantasai> fremy: If you nest with Option 3, cannot copy paste without running into problems maybe <fantasai> fremy: Both this and option 4 have this ability <fantasai> fremy: I agree that when you change from one rule to nesting, you have t oadd some stuff before/after, but I think it's worth mentioning that for Option 3 that if you go from nesting to not nesting or vice versa <fantasai> fremy: you need to change things <fantasai> fremy: refactoring is a pain in both cases, but it's different kind of paint <fantasai> fremy: but I wanted to mention this important point <tantek> copypaste++ and and also +1 for adding/removing nesting without having to rewrite the contents as a design principle <Rossen_> q? <argyle> q+ <Rossen_> ack fremy <jensimmons> +q <fantasai> argyle: I'm confused by the copy/paste scenario? I'm writing CSS using nesting 1, 2, 3, <fantasai> argyle: I copy paste stuff in and out of socpe, in and out of ..., just use & everywhere <fantasai> fremy: You decided to use & everywhere, but if you remove nesting it'll break <Rossen_> ack argyle <fantasai> argyle: it only breaks with :has() <fantasai> fremy: that's not what I mean, what I mean is if you have a CSS file with a lot of rules, they can start with any selector <fantasai> fremy: html or p or whatever <fantasai> fremy: If you want to take all these rules and nest them, and say they only apply in this div with special ID <fantasai> fremy: you have to add & to selectors or they will break <fantasai> fremy: You can't just copy paste them into the brackets <fantasai> argyle: Concern in general, & makes it better and more clear <fantasai> fremy: Even if it was required, you would have to add these when you paste into nested context <fantasai> fremy: When you have a stylesheet with normal selectors, if you want to nest this stylesheet, you have to add & before every selector or it won't work <fantasai> argyle: I would like to see examples <fremy> stylesheet was " html { color: red } <fantasai> Rossen_: Sounds like some conversation paste each other, but 2-3 line example from fremy you will be able to see what he means about usability <fremy> if you want to nest this in #id <fremy> "#id { html { color: red } }" is not valid <fantasai> argyle: I've been using this stuff, it's not just theoretical <fantasai> argyle: I have 100s of lines of nested lines of CSS, I don't find a portability issue <fremy> you have to go and edit "#id { & html { color: red } }" <fantasai> argyle: I don't see what you're talking about <Rossen_> q? <fremy> and you have to do that for potentially a lot of selectors <fantasai> argyle, you're one of 50% of authors who think it's fine to prefix all their style rules everywhere forever with &. The other 50% of authors don't want to do this. <argyle> i'm in both camps, trying both.. <fantasai> jensimmons: I really like this option, I like this a lot. I like it better than Option 4 <fantasai> jensimmons: what I would hope is that folks who've done a lot of work on this, and advocating to make this reality <fantasai> jensimmons: I hope that you are honestly willing to consider these other possibilities <fantasai> jensimmons: what's interesting about this is that it's a deviation from how web developers have thought about nesting from e.g. sass <fantasai> jensimmons: it is more like writing an @rule and doing stuff inside it, isntead of having the shape from sass <fantasai> jensimmons: but I don't think we should reject out of hand <fantasai> jensimmons: there is something elegant of it <miriam> q+ <fantasai> jensimmons: and I thinkw e ened to think of the full range of ppl who write CSS, from students to hobbyists to professionals that write lots of JS to professionals that do other type of software engineering to professionals that do [msised] <fantasai> jensimmons: want it to be not breaking <fantasai> jensimmons: make it easy to understand <fremy> q? <fantasai> jensimmons: think this proposal is very elegant and straightforward <fantasai> miriam: 2 things <fantasai> miriam: 1. This proposal is very much like @scope, doesn't have scoping aspects but otherwise the shape of it is basically identical to socpe <fantasai> miriam: I don't know if that's positive or negative, but worth pointing out <fantasai> miriam: I agree with Jen about who we should think about, but also with Tab about how this seems problematic <fantasai> miriam: copy/paste is pitched as an advantage, but you're not abile to copy/paste int osomething not @nest, takes a lot of adjustment <fantasai> miriam: All of these proposals have tradeoffs, and we keep fighting about which tradeoffs, and aruging which are better for authors <Rossen_> ack jensimmons <Rossen_> ack miriam <fantasai> miriam: I think all of theme are hard for authors, but we need to pick one <fantasai> fremy: I thought we agreed to make a survey and see what ppl think, but we now have another proposal <fantasai> fremy: but we should probably should do that <fantasai> Rossen_: Agreed <fantasai> Rossen_: getting away from topic which is review of this proposal <fantasai> Rossen_: appreciate plinss for describing the proposal and its pros/cons wrt others <jensimmons> q+ <fantasai> Rossen_: My hope is that we'll get to next step and at some point will need to close the door on more options <fantasai> Rossen_: and start scoping down which we will go with, which will work best for authors <fantasai> Rossen_: with that, I want to move on... <fantasai> Rossen_: but I want to simply take the conversation down to a closure with next steps being, let's figure out what ppl think about these options in a representative way <fantasai> Rossen_: and then come back to making some choices <fantasai> jensimmons: I would really love for us to come to a decision, a final decision, by the end of the year. That might be a little ambitious <fantasai> jensimmons: I do think we're close. <fantasai> jensimmons: we could just decide on Option 3 and call it a day, but I think we do want to have a bit more debate about 4 or 5 <fantasai> jensimmons: but I also hear the clock ticking, so would like a decision by early January <fantasai> Rossen_: Appreciate pressure and urgency, and hope we'll have something end of year or beginning of next <fantasai> Rossen_: Ok, let's wrap up this conversation. Thanks plinss for bringing this up <fantasai> Rossen_: one last closing question, do we have a path forward to organize non-biased survey, and who would that be? <fantasai> Rossen_: jensimmons, can you do that? You seem most non-biased :) <fantasai> fremy: I think last time miriam, TabAtkins, fantasai and leaverou agreed to help <fantasai> plinss: I can edit the new proposal into the table <fantasai> -> https://drafts.csswg.org/css-nesting-1/proposals <fantasai> ACTION: plinss to update proposals table <fantasai> ACTION: jensimmons, miriam, leaverou, fantasai, etc. to create survey |
I think the bigger issue is author preconception. @LeaVerou's Twitter polls again confirmed that authors want nesting to be as terse and relaxed as possible. If the concern is to pick the right syntax for the future regardless of what preprocessors have done in the past then I don't think another author survey will be helpful. Authors will pick proposal 3. I don't think it is possible to design a survey for todays authors that will have a different outcome. I personally would be fine with proposal 1, 3 or even 5. |
I think @romainmenke is very likely right about predicting the poll result. But I guess we'll see. I very much appreciate having various alternative proposals to consider, and have backed several of them at this point. But I disagree with the premise mentioned a few times that some proposals are more 'programmer focused' while others are more appropriate for a broad CSS audience. So far all the seriously-considered proposals have been designed around CSS syntax, and they have all involved awkward tradeoffs that authors will need to get used to. This isn't a philosophical debate about the soul of CSS, it's a practical debate about how to make nesting work around some inconvenient parsing limitations. Anyway, I want to follow-up a little on my mention of The overlap between
|
One other advantage to this proposal, An author seeing: foo {
color: red;
& bar { color: blue; }
} or foo {
color: red:
} {
bar { color: blue; }
} has no keywords any search engine is going to provide reasonable results for (and no obvious indication that nesting is happening, either could be interpreted as typos). |
As an author, I would be strongly against something that requires me to create a whole separate rule like that. Part of the benefit of nesting is organizing my code into portable "chunks", so I can copy a rule and have all the CSS needed for a "component". It seems that option 5 breaks this, unless I'm missing how exactly it's supposed to be used. |
CSS is full of symbols that have the same issue: |
I don't understand your point here at all. All the CSS for a "component" is within the |
Doesn't mean we're doing people any favors by adding more... (in fact, there's even a TAG design principle about this :-) Another point, how would proposals 3 & 4 be feature detectable? (I accept it can likely be done, but in an obvious way?) |
My point wasn't "there is precedent for this bad thing and thus it's fine", it was "CSS already does this and authors don't seem to have any trouble googling things". So I don't think the TAG principle you linked applies here. Learnability is one component of usability, efficiency is another, equally important one. For commonly typed things, brevity becomes more important than learnability.
|
CSS has rejected other uses of sigils in the past for precisely the searchability issue, and it's not necessarily obvious to an author to search for 'ampersand' instead of
Maybe, but seems fragile, what if there are other places |
Yes, because to use a symbol, the feature needs to be needed frequently enough that brevity is important. This is not true for every feature, but it certainly is for nesting.
Other places …in a selector?
Yes, it is. Really. |
And in this proposal, even the
Yes, in principle it could be used in a selector in some context that isn't nesting. We have a limited number of ascii-friendly sigils to use and may need to repurpose it at some point. If the need is to detect the feature of nesting (or the other theoretical usage), it may not be enough to disambiguate. Being able to detect an actual at-rule is more specific, and more obvious. You also still never explained your initial objection about having to create a "whole separate rule" and the perceived componentization issue. |
Below is a slightly altered version of this example from the spec (the difference being table.colortable td {
text-align:center;
}
table.colortable td .c {
text-transform:uppercase;
}
table.colortable td:first-child, table.colortable td:first-child+td {
border:1px solid black;
}
table.colortable th {
text-align:center;
background:black;
color:white;
} Converted to syntax 5 it becomes this: (UPDATE: Updated the code to remove the unnecessary @nest table.colortable {
@nest td {
& {
text-align: center;
}
.c {
text-transform: uppercase;
}
&:first-child,
&:first-child + td {
border: 1px solid black;
}
}
th {
text-align: center;
background: black;
color: white;
}
} Actions that were needed:
While doing this:
Furthermore, with this fifth proposal, I noticed:
Comparing this to proposal 3:
table.colortable {
& td {
text-align: center;
.c {
text-transform: uppercase;
& span {
color: hotpink;
}
}
&:first-child,
&:first-child + td {
border: 1px solid black;
}
}
& th {
text-align: center;
background: black;
color: white;
}
} This last code example –using proposal 3– is imo much more consistent than the proposal 5 version. |
A few corrections:
Remember, in this proposal So it's actually: @nest table.colortable {
@nest td {
{
text-align: center;
}
.c {
text-transform: uppercase;
}
&:first-child,
&:first-child + td {
border: 1px solid black;
}
}
th {
text-align: center;
background: black;
color: white;
}
} |
Thanks for clarifyin. Updated the code to remove the unnecessary |
In option 3, which is the current state of the spec,
I still don't understand what problem you are seeing. You think browsers will implement
Copying two rules (two sets of |
I think option 5 has an issue with progressive enhancement. With options 3 and 4 I can write rules for the nesting root, then add on a nesting block. Then, for browsers that do not support nesting I have to repeat the nesting block in an But with option 5 I have to repeat both the nesting root and the nesting block in my Not a big issue long-term, but annoying for the transition. |
Yes, you'd have to repeat the outer rule. But, the point of nesting is to make the stylesheet smaller and more maintainable. It completely defeats the purpose to have an |
Instead of |
Unfortunately that would require arbitrary lookahead during parsing. It also gets weird when one of the legal contents is a style rule without a selector, so you'd get: selector {{{ color: red; } selector { color: blue; }}} Not sure that helps readability, maintainability, or searchabilty. |
This should be used instead if required. |
Why not? The You're adding a bunch of complexity and author pain to save 4 characters. |
If you search for “& css”, the first top hits are about CSS nesting (in SASS). |
FWIW, despite everything that I don't like about this proposal, lookahead wouldn't be a problem for Blink here from what I can see. We know we're parsing a selector, so we don't have to backtrack when we see the |
Closing as WONTFIX by CSSWG resolution see minutes |
The fundamental problem with allowing nested style rules is disambiguating properties from nested rules.
So far, every proposal has focused on taking a regular style rule and creating a syntax to identify selectors within it. What if we turned that around?
My proposal is to have an at-rule that has a selector, and contains nothing but style rules (and other at-rules), whose selectors are relative to the at-rule. We can then have a special block within the at-rule to hold properties that apply to the nesting root,
E.g.
would be equivalent to:
You could also, of course nest the at-rules:
would be equivalent to:
It may also be possible to omit the
&
and just use a bare{}
block within the at-rule to hold properties.This requires no changes to existing parsing, OM, or behavioral rules and has a straightforward OM for the new at-rule.
The text was updated successfully, but these errors were encountered: