Skip to content
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] Choose Nesting syntax — Option 3, 4 or 5? #8248

Closed
jensimmons opened this issue Dec 21, 2022 · 15 comments
Closed

[css-nesting] Choose Nesting syntax — Option 3, 4 or 5? #8248

jensimmons opened this issue Dec 21, 2022 · 15 comments
Labels
css-nesting-1 Current Work

Comments

@jensimmons
Copy link
Contributor

Let’s choose between Option 3, 4, and 5 for CSS Nesting syntax.

With over 2,500 votes, the results of the latest developer survey (not counting the last 5 hours) were:

  • Option 3 — 80%
  • Option 4 — 7%
  • Option 5 — 13%
@jensimmons
Copy link
Contributor Author

As I wrote the article, I worried people would skim it too quickly and not see there’s a difference between Option 3 and Sass syntax. So, as a thought exercise, I ran some numbers.

Let’s imagine a third of the people who voted for Option 3 misunderstood the details, and mistakenly believed they were voting for Sass syntax, changing the results to this:

  • Option 3 — 53%
  • Sass syntax — 27%
  • Option 4 — 7%
  • Option 5 — 13%

Even then, Option 3 is preferred by a majority of those responding.

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed [css-nesting] Choose Nesting syntax — Option 3, 4 or 5?, and agreed to the following:

  • RESOLVED: Reject options 4 and 5, go with option 3 with continuing refinement
The full IRC log of that discussion <TabAtkins> jensimmons: We ran this survey and wrote an article on webkit.org
<TabAtkins> jensimmons: Even tho it was bumpy, i think the reuslts are very clear
<TabAtkins> jensimmons: There's a lot of comments on twitter/masto/HN
<TabAtkins> jensimmons: And a very clear pref for Option 3
<nigel> s/NIgel_Megitt/Nigel_Megitt
<plinss> q+
<TabAtkins> TabAtkins: sounds like strong consensus
<TabAtkins> plinss: I have concerns.
<TabAtkins> plinss: I don't think we should decide purely by the poll.
<TabAtkins> plinss: That'd be fair if we had 2 or 3 options that were equiv
<Rossen_> ack plinss
<TabAtkins> plinss: But I think this is more involved than that, there are ramifications people werne't taking into account
<TabAtkins> plinss: Looks like a lot of people just want Sass, that's most votes for Option 3.
<astearns> q+
<TabAtkins> plinss: And the more I think about it, the more concerns I have with mixing selectors and properties.
<TabAtkins> plinss: Really not happy with the future constraints we're putting on the language.
<TabAtkins> plinss: Fundamental problem is tha tanything that's not obviously a property defaults to be a selector, adn that constraitns our abilitiy to ever extend property syntax again.
<TabAtkins> plinss: The default needs to be that it's a property and we need an indicator that it's a selector
<astearns> q-
<Rossen_> q?
<TabAtkins> plinss: Like @nest. I know that was rejected for verfbosity, but I'd be okay with a bare @
<TabAtkins> plinss: A lot of people are also supportive of OPtion 3 with mandatory &, and we could have @ do that.
<TabAtkins> plinss: So that's a compromise I can live with.
<TabAtkins> q+
<TabAtkins> astearns: I think I agree with peter to a certain extent, but I would want to have an idea of the kinds of things we are cutting ourselves off from
<TabAtkins> astearns: I don't know what it is that prioritizing selectors over props will make difficult to extend in the future
<TabAtkins> plinss: For example, I think we wouldn't hav e been able to do custom props the way we did if we had this
<TabAtkins> plinss: Once upon a time idents started with a letter or a single dash, and I'm not sure what else we'll want to do with properties, but we'll have to invent some weird syntax.
<TabAtkins> astearns: I think I agree with the argument that if Sass nesting had never existed, that when we were adding this feature we'd do something more like option 5; we wouldn't consdier option 3 at all.
<TabAtkins> astearns: but the existence of Sass nesting is a design constraint that we really do have to respond to, and option 3 does do that
<TabAtkins> plinss: Another alt is we say screw it and adopt the sass syntax
<TabAtkins> plinss: A lot of people are opposed, but i'm curious if we can't afford it.
<TabAtkins> plinss: Back when we first started this, at Gecko, I had everyone telling us we couldn't do CSS due to perf.
<TabAtkins> plinss: Maybe we can afford a recursive descent parser now and do Sass syntax.
<TabAtkins> plinss: And tha'ts something I'd be okay with too.
<fantasai> s/too/too, because you're fully resolving everything/
<TabAtkins> plinss: I think it sitll gives us some potential for conflict but it's not as bad.
<fantasai> scribe+
<fantasai> TabAtkins: What we are prevented from extending in the future
<fantasai> TabAtkins: 2 aspects: need to avoid selectors and ??
<fantasai> TabAtkins: on selector side, means we can never add a new bare function syntax
<fantasai> TabAtkins: We have pseudo-classes that are functional, that's fine. But we can't add a plain function to selectors
<fantasai> TabAtkins: That doesn't seem like it would be a problem, lots of space for symbol-prefixed
<fantasai> TabAtkins: over on properties, need to start property with either ident or function
<fantasai> TabAtkins: can put stuff after ident/function
<fantasai> TabAtkins: just can't put before the property
<fantasai> TabAtkins: That does mean if we had done this in the past, we'd have had to do some compat analysis about allowing ident to have --start
<Rossen_> ack TabAtkins
<fantasai> TabAtkins: that was a change, but technically also needed to care about compat because previously invalid now valid
<fantasai> TabAtkins: those sorts of changes are likely ... if we need to change ident syntax in the future, we can navigate those, and unlikely to look like selectors too much
<fantasai> TabAtkins: doubt problem, and we have compat tools to figure it out
<fantasai> TabAtkins: beyond changing ident syntax, I don't think we're losing any important syntax space
<fantasai> TabAtkins: some ideas to put things before the properties, e.g. early sketches of additive cascade used + before/after property name to indicate prepend/append
<fantasai> TabAtkins: but we can choose an alternative syntax
<fantasai> TabAtkins: in practice not a large restriction
<fantasai> TabAtkins: large amount of syntax space we've left unexplored
<fantasai> TabAtkins: and rare places where might collide, can analyze so not shooting in the dark
<fantasai> TabAtkins: More generally, we've been talking about nesting syntax for a year, need to close the door at some point
<fantasai> TabAtkins: can't keep having ppl propose new alternatives
<fantasai> TabAtkins: latest option 3 is good improvement, and people like it
<fantasai> TabAtkins: if we continue messing around, and ignoring things like 80%-90% poll results, is going to make ppl angry, and won't accomplish anything
<fantasai> TabAtkins: more polls will result in similar result
<argyle> q+
<jensimmons> q+
<fantasai> Rossen_: Want to close the discussion, lots of tension but I also want to get to at least one more issue
<fantasai> Rossen_: will close the queue, drain it, and if we can't have a path for resolution, then we'll put to GH
<TabAtkins> plinss: I hear what your'e saying about syntax
<fantasai> plinss: I hear what you're saying about syntax, but just want to be clear that we're blocking ourselves off from prepending to an ident. I think it's a decision we'll reget
<TabAtkins> plinss: We're blocking ourselves from prepending a property with anything that's not an ident, and I think we'll regret that
<TabAtkins> plinss: I think default to selectors was the wrong choice here
<TabAtkins> plinss: I'm sympathetic to "we've discussed forever"
<TabAtkins> plinss: But don't think we should take a decision that has problems we haven't throught thru
<TabAtkins> plinss: We ahve responsibility for th elong term
<TabAtkins> plinss: No t just to respond to the long term
<TabAtkins> fantasai: I'm sympathetic to peter's arguments but also agree with TAb that we need to clsoe on this
<TabAtkins> fantasai: In term sof forward compat, we shoudl be setting things up within these decl blocks that the parse stops at either a semicolon or a block
<TabAtkins> fantasai: and you throw out whatever as invalid
<Rossen_> ack fantasai
<TabAtkins> fantasai: Gives us some space to work with
<TabAtkins> fantasai: So we shoudl design invalid in a way that gives us room to extend
<Rossen_> Zakim close queue
<TabAtkins> fantasai: think we can
<TabAtkins> fantasai: and if there's specific bits of syntax we want to leave open for extensions, we can do that
<TabAtkins> fantasai: like if it starts with @ without an at-rule treat as a prop, etc
<TabAtkins> fantasai: But I think we should go with Option 3 as we have it now. Maybe small tweaks to nesure max compatibility, but think we shoudl go with that for now
<Rossen_> ack argyle
<TabAtkins> argyle: Happy to see this discussed
<TabAtkins> argyle: Wanted to mention we can't do exact Sass syntax. We can match as much as we can, but "just do Sass" isn't on the table. We've adopted as many tradeoffs we can.
<TabAtkins> argyle: So I think this has been in the tumbler enough to be a pearl
<bradk> +1 to possibly prepending ‘@‘ in the future to indicate it is a selector that follows
<TabAtkins> argyle: I like where we are now with all the options
<TabAtkins> (Happy to take an issue for that btw)
<TabAtkins> jensimmons: I think last time I expressed my opinion I was agaisnt option 3 and liked 4, and liked 5 when it came up
<TabAtkins> jensimmons: But while writing the article I started really hating OPtion 4 with a passion. There's still something about 5 that appeals, but I really think we should resolve on option 3, hopefully today
<lea> q?
<TabAtkins> jensimmons: I agree with Peter that a lot of people potentially didn't understand the gotchas with 3
<Rossen_> ack jensimmons
<Rossen_> Zakim, close queue
<Zakim> ok, Rossen_, the speaker queue is closed
<TabAtkins> jensimmons: But there were so manyc omments from people who really did udnerstand the gotchas, including several asking for madatory ampersand
<TabAtkins> jensimmons: So I think there is enough understanding from webdevs
<fantasai> s/madatory ampersand/mandatory ampersand as a way to compensate
<TabAtkins> jensimmons: Also convos internally in Apple - maybe we will find a way to do lookahead that's fast enough.
<TabAtkins> jensimmons: so we would be able to relax the syntax restriction
<TabAtkins> (Option 3 is indeed extensible to Sass version later, if we want)
<TabAtkins> jensimmons: I agree polls shoudln't dictate us, but given the fact that Option 3's big gotcha is webdevs might get confused, but watching their comments I got a lot of confidence tha toption 3 is the way to go
<bradk> +1 to resolving on option 3 today
<TabAtkins> Rossen_: So I've closed the queue. There's some clear statement of concern raised by Peter, and a clear voice of wanting to adopt 3 and make it work.
<bramus> +1 on moving foward with option 3
<lea> Many people got confused at my polls as well. I think the article did a great job at explaining the options, and no matter what we do, people will get confused anyway.
<lea> +1 on resolving on option 3 today
<TabAtkins> Rossen_: So I'd like to try for a resolution, we'll see if we get a strong objection.
<TabAtkins> plinss: I'm objecting to option 3 as it stands. Okay with trying to refine it further, but don't think it's the right decision as it stands.
<lea> Related to refining option 3 further: https://github.com//issues/7961
<TabAtkins> Rossen_: So to be clear - we want to narrow on Option 3 with options to refine it.
<TabAtkins> Rossen_: [doing a straw poll]
<TabAtkins> Rossen_: Options are 3, 4, or 5 as stated in the poll.
<bradk> 3
<argyle> 3
<flackr> 3
<lea> 3
<TabAtkins> 3
<fantasai> 3
<bramus> 3
<jensimmons> 3
<ntim> 3
<dholbert> 3
<matthieudubet> 3
<miriam> 3
<rachelandrew> 3
<fantasai> Conditional on ; terminating the selector parse
<TabAtkins> It does already do that, yeah
<TabAtkins> (the details are in Syntax)
<lea> q?
<TabAtkins> See https://w3c.github.io/csswg-drafts/css-syntax/#consume-qualified-rule for the ;-termination
<TabAtkins> fantasai: Note that my support is specifically if semicolon terminates the selector parse, so we can extend in the future more safely
<dbaron> how many valid selector beginnings are we accepting if we take option 3?
<fantasai> TabAtkins: Algorithm already terminates on ; if you think you're parsing a selector
<dbaron> (is it more than &, :, and combinator symbols?)
<fantasai> (no, I don't think it is)
<TabAtkins> dbaron, anything other than ident or function is a valid selector beginning, so long as you don't encounter a ; before the {
<chris_> 3
<dbaron> abstain
<nigel> abstain
<astearns> abstain
<jfkthame> abstain
<ydaniv> abstain
<smfr> abstain
<florian> abstain
<Rossen_> abstain
<dbaron> (abstaining because I think we could refine 3, I think)
<nigel> (Having read the comments around the poll, refining 3 seems like the best option)
<bradk> or some people are on call but not paying attention
<TabAtkins> Rossen_: Looks balanced between 3, abstain, and not saying anything, don't think we can resolve on that
<astearns> I think we need an issue on the specific problem of 3 boxing in syntax, with examples and possible ameliorations
<lea> q+
<TabAtkins> Rossen_: Can we leave Option 3 as the only path forward to refine?
<TabAtkins> Rossen_: Peter are you okay with that path forward?
<TabAtkins> plinss: I'm fine with improving our efforts on improving option 3, i'm not okay with excluding any new ideas
<TabAtkins> Rossen_: Right, just want to narrow down to option 3 from the options we have now
<TabAtkins> Rossen_: dbaron, you had an issue?
<TabAtkins> dbaron: Think we're better off working it out in an issue.
<flackr> I think a parser switch would be fine if we had to do it. Could be confusing but developers shouldn't switch back to property syntax after nesting selectors.
<TabAtkins> Rossen_: So we're rejecting Options 4 and 5, and continuing to refine Option 3. Is that a resolution?
<astearns> I disagree with that suggestion, flackr :)
<flackr> :)
<TabAtkins> lea: It looksk like there's a strong sentiment behind option 3 "but refine it", but it seems tha trefining means different things to different people
<TabAtkins> lea: Peter seems to be saying something more - not mixing selectors and decls in the same context.
<TabAtkins> lea: So it might be reasonable to have a lis to fthings we're looking to refine.
<TabAtkins> plinss: to clarify, i'm not fully opposed to mixing selectors and props at all, i just think we need a system that favors a property unless it's explicitly indicated as a selector
<TabAtkins> Rossen_: I want to close down this discussion today. So proposed resolution: narrowing down to Option 3, with continuing improvement before it's accepted
<dbaron> I think plinss's "single mechanism" might be too strong, but I think we could certainly find a different balance of which future syntax goes down the property path versus the selector path without changing any valid-today syntax in option 3.
<TabAtkins> fantasai: Just want some clarity - it seems Peter wants to separate out property/selector syntax with some symbol that indicates "you're now in selector mode" and he wont' accept anything other than that. That's not option 3, it's a previous option we've already considered.
<TabAtkins> fantasai: But OPtion 3 is interweaving mostly freely.
<argyle> option 1 as nesting-1, work out option 3 as nesting-2.. still think that's a valid plan forward
<chris_> we can go back to that previously rejected option if there is new information, yes
<TabAtkins> dbaron: I think one of peter's concerns was the % of stuff that goes down selector vs proeprty path, and where future things that are invalid today will go
<TabAtkins> dbaron: I think we can work out something that puts less stuff down the selector path and more down the property path.
<TabAtkins> fantasai: I think things that are invalid today, both go down the same path - parse until you hit the semicolon then throw it away as invalid.
<TabAtkins> plinss: I'm fine with david's refinement. Don't need a single way to say it's a selector - i'd prefer it, but a few ways will work too.
<TabAtkins> fantasai: Right now the final indicator is a semicolon or a {.
<TabAtkins> fantasai: if you're saying "i want specifically the three symbols" not combinators, that's something else
<TabAtkins> fantasai: If that's the main ojbection we can go back and say you *have* to start the selector with a simple selector
<lea> q?
<TabAtkins> plinss: My problem with that is any random new combiantor we add will hav eto be treated as a selector. It's open-ended, and I want it to not be open-ended. that's the crux of my ojbection.
<TabAtkins> (this was a really long 10min timebox)
<TabAtkins> lea: We're already nearly full on combinators anyway, probably future ones need to be /foo/ or something
<TabAtkins> plinss: We can maybe say "only today's combinators and a slash, nothing else", but I think that's limiting
<fantasai> I agree with that being too limiting
<dbaron> (I think we only have one or two ASCII characters left for combinators anyway.)
<TabAtkins> Rossen_: Ending the topic. I called for objections. Are there any?
<TabAtkins> Rossen_: No objections.
<chris_> \o/ progress!
<TabAtkins> RESOLVED: Reject options 4 and 5, go with option 3 with continuing refinement

@LeaVerou
Copy link
Member

LeaVerou commented Dec 21, 2022

As I mentioned in the call, it would be good to define what kind of "continued refinement" we are looking for and open separate issues.

Some issues we've heard with option 3 are:

  1. Some people suggest making & mandatory at all times. The issue for that: [css-nesting-1] Should prefixing nested selectors be mandatory? #8270
  2. Others want to go the opposite way, and make it optional in even more cases. Many comments to the WebKit article by developers were basically about this. We already have an issue about this: [css-nesting-1] Can we relax the syntax further? #7961
  3. @plinss’s objection was related to how constraining this would be for future syntax; he is concerned that if anything that starts with a selector character is assumed to be a selector this will restrict future extensions significantly, and instead wants to limit what signifies that something is a nested rule. This to me sounds a lot like the previous nesting syntax, but perhaps there is another option. Peter opened an issue: [css-nesting] Problem with mixing properties and selectors #8249

Is there something else we could refine?

@tabatkins
Copy link
Member

Mandatory ampersand won't help - .foo & {...} still needs to be valid.

@LeaVerou
Copy link
Member

LeaVerou commented Dec 21, 2022

Mandatory ampersand won't help - .foo & {...} still needs to be valid.

The reasoning of those folks is not to facilitate parsing, but to improve clarity (as they see it). .foo & still has an ampersand in it.

@plinss
Copy link
Member

plinss commented Dec 21, 2022

The reasoning of those folks is not to facilitate parsing, but to improve clarity (as they see it). .foo & still has an ampersand in it.

But requires indefinite lookahead to determine. If we're going to add indefinite lookahead, we can just use the SASS approach.

@tabatkins
Copy link
Member

No, .foo & doesn't require indefinite lookahead. In the current rules, we see it's a style rule on the very first token (.).

@plinss
Copy link
Member

plinss commented Dec 21, 2022

But if the & is required, you either have to have indefinite lookahead to find the &, or something like .foo bar baz {... is going to get rejected, where it could theoretically have been acceptable as a property at some point.

@tabatkins
Copy link
Member

Right, which is part of why I don't think "required &" does anything useful.

@dbaron
Copy link
Member

dbaron commented Dec 21, 2022

I opened #8251 as a followup for the thing that I was thinking about (in response to Peter's comments) on today's call.

I'd also note that Peter opened #8249, which is distinct from that.

@Loirooriol
Copy link
Contributor

Mandatory & wouldn't be useless, it would bring clarity to authors writing or reading CSS. E.g. a nested ::before can be misunderstood as &::before or & ::before, but it's clear with the &.

Personally I plan to always use &, and use linting to enforce it if the spec says it's optional. So I prefer a mandatory &.

@SebastianZ
Copy link
Contributor

And for the record, there was also already some discussion earlier about requiring & at the beginning of every nested selector. This avoids lookaheads entirely but also burdens writing nested selectors.

And before somebody asks, .foo & {... would be expressed as & .foo & {... in that case.

(Note that I don't advocate for that syntax, I just wanted to mention it again, as it seems people forgot about the options that were previously discussed.

Though I am with @Loirooriol here and would always prepend my nested selectors with &. And I'd generally avoid putting & in the middle of a selector as that rather confuses than helps, IMO.)

Sebastian

@romainmenke
Copy link
Member

romainmenke commented Dec 23, 2022

Some people suggest making & mandatory at all times. We should open an issue on this (and replace this sentence with a reference).

Mandatory & in itself is not really interesting I think.
As @Loirooriol said this can be achieved with a linter, so I don't see the point of enforcing this in the specification unless it offers some advantage.

These cases are not helped by mandatory & :

  • div:has(> &) compound selector with & in a functional pseudo
  • div & complex selector with & not in the first compound

I am unsure what mandatory & is supposed to solve.


And before somebody asks, .foo & {... would be expressed as & .foo & {... in that case.

Using & as a prefix and as as reference to matched elements of the parent block is highly confusing and limiting.

ul {
  & li & {
    /* style only ul elements that are in other ul li elements */
  }
}

Is the first & a prefix to indicate a style rule or is it a reference to ul?


Can someone open an issue for this (as @LeaVerou indicated) and describe the benefits/details of mandatory &?

@SebastianZ
Copy link
Contributor

Can someone open an issue for this (as @LeaVerou indicated) and describe the benefits/details of mandatory &?

I created #8270 for that now, so we can continue the discussion there.

Sebastian

@jensimmons
Copy link
Contributor Author

I'm going to close this issue, since we succeeded in choosing between Option 3, 4 and 5. Refinement of Option 3 can continue in new issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
css-nesting-1 Current Work
Projects
None yet
Development

No branches or pull requests

9 participants