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] Problem with mixing properties and selectors #8249

Closed
plinss opened this issue Dec 21, 2022 · 95 comments
Closed

[css-nesting] Problem with mixing properties and selectors #8249

plinss opened this issue Dec 21, 2022 · 95 comments

Comments

@plinss
Copy link
Member

plinss commented Dec 21, 2022

As mentioned I'm opening a new issue to outline the objections I raised in the call today and to discuss paths forward.

My primary objection to the current syntax is that mixing properties and selectors without a clear distinction places unacceptable (to me) restrictions on the future design of the CSS language.

An implementation parsing a style declaration will need to presume anything that doesn't start with an identifier or function is a selector, which restricts our ability to ever extend property declarations with anything that doesn't start with an identifier or function. Furthermore this restricts our ability to ever extend the definition of an identifier or a function. As an example, if this were implemented first, we could never have added custom properties with the current syntax (which redefined identifiers).

Alternatively, we could limit selector combinators to the current set and a limit extension path, like /<name>/, this would place restrictions on future selector syntax and potentially add more confusion as to the rule of when a & or the :is() hack is required. Not a fan of this.

I see two paths forward (and welcome other suggestions):

  1. We remove the lookahead restrictions on the parser and 'simply' adopt the SASS syntax. The lookahead restriction came about 25 years ago when there were real concerns that CSS would be too slow to ever implement in a browser and everything was focused on performance. I'd like to see some experimentation and real-world data to check that assumption and see if advancements in processor speed and RAM availability allow us to relax that.

  2. We add something that clearly distinguishes selectors from properties within a style declaration.

Something like:

div {
  color: red;
  @nest span {
    color: blue;
  }

is fine by me, but I accept that this has been proposed in the past and rejected.

A compromise I'd be OK with would be treating a bare @ inside a declaration as the equivalent to @nest (and possibly allowing @nest to be optional for those wanting clarity). This is functionally equivalent to requiring the & (which many people in the polls preferred), but also handles cases where the & isn't the start of the selector without adding lookahead. e.g.:

div {
  color: red;
  @ span {
    color: blue;
  }
  @ &:hover {
    color: green;
  }
  @ section & {
    color: yellow;
  }
}

This leverages the fact that @ is already CSS's universal escape hatch and clearly distinguishes properties and selectors, allowing unrestricted extensions of either in the future. It also minimizes verbosity as the majority of nested selectors can simply start with an @ and requires no other changes or special rules to learn.

@jensimmons jensimmons added the css-nesting-1 Current Work label Dec 21, 2022
@tabatkins
Copy link
Member

As an example, if this were implemented first, we could never have added custom properties with the current syntax (which redefined identifiers).

This isn't accurate. We couldn't have naively redefined identifiers; we'd have had to do some compat analysis to check if it would actually cause a problem or not. (And we'd have found it was perfectly okay, since --foo wouldn't be the start of any valid selector anyway, so usage would be minimal.)

The hard restriction we have is that we can't introduce new property syntax that looks like a (relative) selector. So nothing that puts any of >+~.:#[ at the start, for example. (.:# could be used if followed by whitespace or some other non-ident, tho.)

(Unless we end up solving the perf problems with the unbounded lookahead. Then we can potentially do a lot more so long as they're eventually distinguishable, tho we'd likely still want to be careful about mixing things too hard.)

Alternatively, we could limit selector combinators to the current set

This won't help, as descendant combinators mean the nested selector can start with any of the simple selector glyphs (.:#[). We'd also have to restrict our ability to add new simple selectors, not just combinators.


"Mandatory @nest" was rejected by the group already, and verbosity wasn't the sole concern about it; copy/paste ability is still affected even if you reduce the required prefix to a single character.

@jensimmons
Copy link
Contributor

  1. We remove the lookahead restrictions on the parser and 'simply' adopt the SASS syntax… I'd like to see some experimentation and real-world data to check that assumption and see if advancements in processor speed and RAM availability allow us to relax that.

I believe everyone agrees that removing the lookahead restrictions on the parser and adopting SASS-style syntax would be ideal. This is not something for which we can debate the pros and cons. It's all pros.

Implementation experience is the only path forward to find out whether or not if this is a viable alternative. The teams currently implementing CSS Nesting need to try it, test performance, and see what happens. To attempt to figure out a way to make it fast. If so — fantastic, decision made. If not, well, decision made.

I know folks are already working to see such implementation experience happen. Meanwhile, we should discuss what to do if removing the lookahead restrictions is not a viable solution.

@fantasai
Copy link
Collaborator

fantasai commented Dec 21, 2022

@tabatkins and I both disagree that splitting style rule and declaration parsing on non-ident start over-restricts the future of CSS declaration syntax. But to understand why, we need to consider:

  • CSS declaration syntax has been extremely stable for almost three decades. Unlike Selectors, it isn't an area where we do lots of interesting syntactic things.
  • What's closed off for future extension isn't everything we pipe through the selector path today. It's everything that's invalid today.

We're not just reserving everything that has an ident start for declarations: we're reserving everything that results in an invalid sequence, whether that sequence is parsed in as invalid style declarations or invalid style rules or a mix of both.

Remember the parsing rules being proposed for mixed context are a little different:

  • if we triggered a declaration parse, we swallow up to the next semicolon
  • if we triggered a style rule parse, we swallow up to the next {}-block or semicolon, whichever comes first

The following sequences are all complete invalid constructs: they are thrown away and anything after them starts a new parse. Which means we can interpret them however we want in the future.

@foo anything except semicolon { anything }
random stuff: other stuff { anything } anything;
random(stuff): other stuff;
!other stuff: more stuff;
++extra stuff: stuff;
(anything): anything;

The only thing we're closing off entirely is a new construct that maps to the following sequence:

  1. a sequence that starts with a symbol (and thus triggers style rule parse)
  2. a {}-block (which thus ends the style rule parse)
  3. a sequence that is currently a valid style rule or valid property declaration (which then gets read in as valid by current browsers)

Basically, we can't introduce new things like:

#stuff starting with a symbol { anything in this block } valid-property: value;
/* new thing all parsed as one declaration */

which doesn't seem very likely for us to add in the first place.

So as long as we're not planning to introduce a new type of property declaration that maps to that, we can introduce any new declaration syntax additions we want in the future. Though for the sake of preserving LALR parsing, we'll want any symbol start to be something that is not currently valid as a selector start token.

I think this is plenty of open space for innovation.

@plinss
Copy link
Member Author

plinss commented Dec 21, 2022

"Mandatory @nest" was rejected by the group already, and verbosity wasn't the sole concern about it; copy/paste ability is still affected even if you reduce the required prefix to a single character.

Yet a significant number of poll respondents advocated for a mandatory & which has the same copy/paste problem, yet seems to be acceptable to developers.

@plinss
Copy link
Member Author

plinss commented Dec 21, 2022

One of my opinions on this whole matter is that what people really want is SASS's behavior, if we can't give them that, then giving them something that's kinda close but has all sorts of weird rules and exception cases (and requires ugly hacks like wrapping perfectly normal selectors in :is() for syntactical purposes) isn't all that helpful in the end.

If people don't like what we deliver and prefer SASS, they can just use SASS. What we deliver should be consistent, logical, easy to explain, and not constrain the future development of the language in any way just to try to mimic a syntax that we really can't mimic properly.

@tabatkins
Copy link
Member

giving them something that's kinda close but has all sorts of weird rules and exception cases

Hyperbole isn't useful here. There is precisely one rule - if your selector starts with an ident, you have to rephrase it somehow.

@plinss
Copy link
Member Author

plinss commented Dec 21, 2022

Not trying to be hyperbolic, and it's not one rule if the answer is 'somehow'. First, authors have to understand exactly what an ident is, then sometimes you have to use a leading &, and other times you have to wrap at least the leading selector in :is() (and yes, that's a hack). Sorry, but that's weird, and while the reasons make sense to us, they won't make sense to most authors. Then, in the future as we add more selector syntax or property syntax the set of rules and exception cases can grow. That's problematic.

@tabatkins
Copy link
Member

"what's an ident" is extremely simple - if it starts with a letter or a dash (and isn't a number). "it feels like a keyword" works just fine for author intuition.

For fixing it, you can do :is() all the time. Appending a & compound is just shorter sometimes. That said, I've just posted a suggestion in #8253 that allows for a completely uniform super-short fix.

@plinss
Copy link
Member Author

plinss commented Dec 22, 2022

My point about idents isn't that it's hard, it's that it's one more thing. i.e. the syntax exceptions aren't 'just one simple rule'. (Also, you forgot that idents can start with escapes, underscores, and non-ascii... In Jenn's poll, she even got the description of when an & is necessary wrong, as she forgot custom properties. So don't try to tell me this ins't error-prone.)

The rules at this point are:

  1. if your selector doesn't start with an ident, use as-is (and know what an ident is), or optionally prefix with &
  2. if it starts with an ident, you must prefix with &
  3. unless you need to use & somewhere else inside your selector, the wrap the first selector in :is()

(And, really, is adding :is() all the time an improvement? I know you're not seriously expecting people to just always wrap the first selector in :is(), but I can see tools doing it.)

Prepending every nested rule with @ actually is one simple rule and there's no special casing, ever. Every selector syntax available now or in the future 'just works' (we already excluded @ from selectors) and there are no conflicts with future extensions to property syntax.

@LeaVerou
Copy link
Member

@plinss

We remove the lookahead restrictions on the parser and 'simply' adopt the SASS syntax. The lookahead restriction came about 25 years ago when there were real concerns that CSS would be too slow to ever implement in a browser and everything was focused on performance. I'd like to see some experimentation and real-world data to check that assumption and see if advancements in processor speed and RAM availability allow us to relax that.

I agree and I have opened an issue about this here with an algorithm that would minimize the performance hit: #7961
Here is a summary:

Sadly the issue was later derailed a bit by those who think & should be mandatory.
One real issue that came out of it was (raised by @lilles) that we'd have to make {} invalid in custom properties for that to work, and there is some limited usage of that in the wild (<0.01%), so it's a tradeoff. (IMO still a worthy one).

@jensimmons

Implementation experience is the only path forward to find out whether or not if this is a viable alternative. The teams currently implementing CSS Nesting need to try it, test performance, and see what happens. To attempt to figure out a way to make it fast. If so — fantastic, decision made. If not, well, decision made.
I know folks are already working to see such implementation experience happen.

See above, when I tried to discuss it in #7961, the Google implementor was very negative:

I don't share this goal; I would like us to just get the syntax (any syntax) specified, out the door and be done with it. So no, I won't be spending resources trying to bend our minds around how we tokenize CSS to this avail; I can NAK what is a non-starter for us, and that's what you'll get.

Great to hear things have changed since then and folks are working on it. Is it the same folks? Which folks are working on it?

@bramus
Copy link
Contributor

bramus commented Dec 24, 2022

In my mind, a merged version of options 3 and 1 tick all the boxes for trying to detect nesting:

  1. Starts with any of the existing combinators >+~? You’re nesting.
  2. Starts with a selector that starts with a symbol.:#[*? You’re nesting.
  3. Starts with the new & combinator? You’re nesting.
  4. Starts with @nest (to be used if you want to use & somewhere but not at the start)? You’re nesting.

Anything else would fall back to the current mechanism to detect declarations, nested at-rules, etc.

Rules 3 and 4 in the list of checks above are the bail out mechanism for when an element selector is nested, similar to what option 1 of the syntax provided us with. These two rules (3 and 4) also play nice with the first two rules, as they can be used together: for example teams can choose to make @nest mandatory by using a linter, while giving other people the freedom to not do so.

(Note that I’m sticking with @nest instead of @ for reasons explained here)

@bradkemper
Copy link
Contributor

bradkemper commented Dec 25, 2022

As an author myself, who has written a lot of CSS both with and without SASS, I don't find these restrictions and workarounds confusing at all. Once people do it a few times they will quickly get used to it. It isn't like even SASS didn't also have things to keep in mind: like always have a semicolon after the last declaration before the nested selectors start. That one still trips me up sometimes, but I know to look for it when there is a problem. And if I have to choose between ALWAYS preceding each rule with @ or @nest, or just doing it when the selector starts with a letter (or underscore, ideograph, or dash or escape), then I'd much much prefer the latter.

Sure something like :is(div) is ugly and sort of a hack, which is why I would like to be able to choose a bare @ as an non-mandatory prefix instead, but even without that I'd like to move forward with what we have. I don't think it is at all burdensome to the author.

@fantasai fantasai added this to Blocking/Urgent in Agenda Scratchpad Jan 10, 2023
@css-meeting-bot
Copy link
Member

css-meeting-bot commented Jan 11, 2023

The CSS Working Group just discussed CSS Nesting Syntax, and agreed to the following:

  • RESOLVED: Adopt Option 3
The full IRC log of that discussion <fantasai> Topic: CSS Nesting Syntax
<fantasai> github: https://github.com//issues/8249
<chris> resolving two color issues in <10min is unprecedented
<fantasai> TabAtkins: I'm willing to summarize what I believe plinss's position is, he can correct
<fantasai> TabAtkins: fear is that the direction the spec is specifying will overly constrain future CSS
<fantasai> TabAtkins: certain new syntactical things in properties or selectors
<fantasai> TabAtkins: proposal is instead to have a dedicated syntax to mark things as a selector
<fantasai> TabAtkins: that way all future syntactical developments would still be allowed
<lea> q?
<fantasai> TabAtkins: and future developments for selectors, which might currently conflict with properties, would also be allowed
<fantasai> TabAtkins: because you have a glyph to mark it as a selector
<fantasai> TabAtkins: related is the 8251 issue, where dbaron discusses the things that trigger selector processing and not currently used by selectors
<fantasai> TabAtkins: this issue accepts mixing of properties and selectors in grammar space
<fantasai> TabAtkins: issue is, we've already discussed previously, what peter is suggesting
<fantasai> TabAtkins: this was Option 1, you had to start with & or @nest or various variants thereof
<fantasai> TabAtkins: This was rejected by WG for verbosity and for copy-paste limitations
<fantasai> TabAtkins: core issue is, WG has looked over that syntax direction and rejected it in the past
<jensimmons> q+
<fantasai> TabAtkins: so I would like to re-affirm that decision, that we're not going to use a dedicated marker syntax of some kind to denote selectors and separate them from properties
<fantasai> TabAtkins: but rather go with current approach of mixing the space
<lea> q+
<fantasai> TabAtkins: make sure the Syntax spec creates a clear dividing line
<TabAtkins> fantasai: I think something Tab didn't emphasize is the core part of Peter's concern for forward compat
<TabAtkins> fantasai: The real effect of forwards compat isn't as - we'r enot limiting as much as it seems like we are
<TabAtkins> fantasai: What we're allowing for the future is anything that's invalid, regardless fo whether it's currently property or selector
<TabAtkins> fantasai: The space of "what is invaidl junk" is actually really broad even with our current proposal
<Rossen_> ack fantasai
<Zakim> fantasai, you wanted to react to ntim
<fantasai> https://github.com//issues/8249#issuecomment-1362033982
<TabAtkins> fantasai: The ony thing we can't expand into is a super-limited syntax space that I can't imagine us actually doing
<fantasai> #stuff starting with a symbol { anything in this block } valid-property: value;
<TabAtkins> fantasai: We cant' start with a symbol, *and* has a curly-brace block *and* is followed by something tha tlooks like a property
<TabAtkins> fantasai: This is the only thing you can't define in the future is a cool new feature
<TabAtkins> fantasai: If it doesn't look like that it's invalid - whether a property or style rule, we throw it out
<TabAtkins> fantasai: And in th efuture we can call it valid either way
<TabAtkins> fantasai: So for concern abou tpainting us into a corner, it's acutally a very small corner and the rest of the space is open
<fantasai> plinss: Just want to clarify a couple points, most of what Tab said is accurate
<fantasai> plinss: it's not necessarily required to have a solution that prefixes every single rule
<fantasai> plinss: also fine to create a new scope
<fantasai> plinss: just nested brackets or whatever, that also solves the copy-paste problem
<fantasai> plinss: just want something that delineates the syntax space
<fantasai> plinss: we did resolve not to do this in the past, but I'm not sure that took everything into account
<fantasai> plinss: not locked by previous decision
<astearns> +1 to not taking older @nest decision as final
<fantasai> jensimmons: I did hear plinss's concerns, and we've discussed exhaustively
<fantasai> jensimmons: but despite downsides, I see all the momentum going towards Option 3 including from webdevs
<Rossen_> ack jensimmons
<fantasai> jensimmons: There was a lot of conversations after ?? meeting, and I appreciate dbaron, fantasai, TabAtkins investigating what we would limit ourslves
<TabAtkins> s/??/final December/
<plinss> q+
<fantasai> jensimmons: but it seems we're not really limiting ourselves, so I think should move forward
<fantasai> jensimmons: want a path that moves us forward and is realistic and acceptable
<Rossen_> ack lea
<fantasai> lea: A lot of things I wanted to say were mentioned by fantasai, still have a lot of space for expansion
<fantasai> lea: but we could expand that space even further by reserving some characters
<Rossen_> ack plinss
<fantasai> plinss: I'm not sure I buy fantasai's argument
<fantasai> plinss: it's not infinite, but there are cases where we wanted to do something but couldn't because shows up in the wild as some weird hack
<fantasai> plinss: I think it'll be limiting
<fantasai> plinss: example is custom properties, couldn't have done that if we had done this first
<fantasai> plinss: I don't want us to get into that situation
<TabAtkins> fantasai: Lets take the custom property eample
<Rossen_> ack fantasai
<Zakim> fantasai, you wanted to respond
<TabAtkins> fantasai: say initial hypthen switched us to selector parsing
<TabAtkins> fantasai: we could do it
<Rossen_> Zakim, close queue
<Zakim> ok, Rossen_, the speaker queue is closed
<TabAtkins> fantasai: You'd throw it out as an invalid selector today
<TabAtkins> fantasai: And that means we can reinterpret it later
<TabAtkins> fantasai: Have you really looked at what the limiting case is?
<TabAtkins> fantasai: The ocnditions are really strict. anything that's currently invalid and gets thrown out, we can reinterpret
<TabAtkins> fantasai: have to keep in mind that the parsing in the nested context isnt' the same as top-level, we truncate at top-level semicolon even in selecto rparsing
<lea> *Nesting itself* is a case where past syntax limits us in what we can do syntactically (going back, maybe we should have used something other than a colon for pseudos), but it's not an insurmountable problem, we are designing around it. We'll design around these issues in the future too, if they come up.
<TabAtkins> fantasai: So there's very limited - can't think of anything you want to do that'll cause a problem
<lea> q?
<lea> q+
<fantasai> plinss: we could solve this with lookahead
<fantasai> plinss: also concerned that we have stuff that's valid for selectors and can't re-use for properties
<fantasai> plinss: selectors can be really really really long, especialy with lists of selectors
<argyle> q+
<fantasai> plinss: thing at the end that changes selector or property, could get into situation that we cant solve without a lot of lookahead
<fantasai> Rossen_: I've closed the queue, 2min past the hour
<lea> regarding exploring lookahead, I tried. Here's a summary: https://github.com//issues/8249#issuecomment-1362739063
<fantasai> Rossen_: Strong arguments in both directions
<fantasai> Rossen_: alan proposed we make nesting an additional call, can make it as soon as next week e.g. 1hr before the main CSS call
<fantasai> Rossen_: but right now we don't seem to have consensus
<lea> +1 to Nesting breakout
<fantasai> Rossen_: or we can take a resolution and ask Peter to file a formal objection
<fantasai> TabAtkins: I would prefer to get the formal objection filed now if it's going to be filed, would rather not be in limbo
<lea> let's try to avoid a FO as much as we can, the TAG is already overworked :(
<fantasai> TabAtkins: fantasai and I explored the syntax space carefully, we don't think there's a real limitation there
<astearns> have to drop
<fantasai> TabAtkins: so I don't think further discussion will yield anything useful
<lea> we need a Nesting breakout even regardless of the FO, don't we? So let's schedule that
<fantasai> Rossen_: ok, we'll try to have a call for nesting, whether this topic is part of it or not is TBD
<fantasai> Rossen_: I will call for objections, and then have a resolution that seems supported by rest of group
<fantasai> Rossen_: Any objections?
<fantasai> plinss: I clearly object. More than happen to have the long call or breakout or sub-breakout or whatever
<fantasai> plinss: happy to let Tab and fantasai convince me that I'm wrong
<fantasai> plinss: and to change my mind
<oriol> I'm more on Peter's side on this topic
<fantasai> plinss: but shy of that, or changing the processing rules, I sustain my objection
<fantasai> Rossen_: It does seem this has been discussed over and over, and I hear support for this from many people
<fantasai> Rossen_: so suggest we resolve this, or take up as additional changes to the current resolution
<fantasai> plinss: We've resolved on Option 3 with this issue open
<fantasai> plinss: still saying we can discuss at the breakout call, so what's point of resolving?
<fantasai> Rossen_: we resolved to discount other options, not to adopt Option 3
<fantasai> [some discussion of what we resolved or didn't]
<fantasai> jensimmons: would be helpful to take the temperature of the room
<lea> fwiw, I agree with plinss that lookahead should be explored more. But not primarily for futureproofing (I think there's enough syntax space that we're not painting ourselves into a corner), but primarily for syntax ergonomics. I'm not convinced it's an unsolvable problem.
<fantasai> fantasai: straw poll, and then close discussion until next week?
<fantasai> Rossen_: A = support Option 3, and B = not support it
<argyle> A
<jensimmons> A
<ydaniv> A
<TabAtkins> A
<fantasai> A
<oriol> B
<bradk> A
<SebastianZ> A
<miriam> A
<plinss> B
<dholbert> A
<GameMaker> A
<flackr> A
<davidleininger> A
<futhark> A
<florian> A
<lea> I find the question unclear, so I'm not voting.
<lea> A
<Rossen_> A
<fantasai> Rossen_: pretty strong signal here, let's go ahead and record this as a resolution. We will try to get the extra nesting discussions, Peter I'm hoping you can proceed with next steps if you want to pursue formal objection or wait until next week
<fantasai> plinss: happy to discuss on breakout call, but want to actually get to it
<fantasai> Rossen_: we've never had a rule that we can't re-open previous resolutions :)
<fantasai> plinss: that's been teh arugment several times
<fantasai> florian: from the other angle, if you do file an FO and are subsequently convinced, you can retract it
<fantasai> plinss: if discusisng in a week, don't need to file an objection today
<fantasai> Rossen_: We'll schedule for next week then
<fantasai> jensimmons: please schedule for next week, it's quite importnat to us
<fantasai> RESOLVED: Adopt Option 3
<fantasai> Rossen_: I appreciate everyone staying longer than usual, we don't almost ever, but this is an important topic to many
<fantasai> Rossen_: we'll schedule an additional meeting next week

@tabatkins
Copy link
Member

I'd like to point back to @fantasai's comment about what precisely the syntax constraints we're actually adopting are.

There are two aspects: things that are currently valid, and things that are currently invalid.

For things that are currently valid, we are indeed closing the door on options. With the current spec, we cannot allow a declaration to start with +, for example, as that's a valid relative selector. (At least, not without paying a lookahead tax that we're currently rejecting.) We cannot start a selector with an ident. As I've said in previous threads, tho, starting a declaration with a symbol is already very likely off the table, given the prevalence of people using a random ascii symbol to "comment out" a property. So in practice we're closing the door on very little new space that wasn't already verboten.

For things are the currently invalid, we are in general not closing the door on anything. CSS's existing forward compatibility parsing rules give us a lot of leeway to reinterpret things, ensuring that "new stuff" (aka invalid stuff in an older browser) gets properly isolated and ignored without screwing up surrounding stuff that is recognized in an older browser.

The recovery rules are:

  • if something invalid is being parsed as a declaration, we throw away tokens until the next top-level semicolon.
  • if something invalid is being parsed as a nested rule, we throw away tokens until the next top-level semicolon or top-level {}-block.

This suggests that (a) we want to bias toward parsing unknown things as nested rules, since the recovery is stricter/safer, and (b) if an older browser parses some pattern as an (invalid) nested rule, and we decide to make that pattern a declaration instead, this is fine so long as it doesn't contain a {}-block followed by something that looks like a complete (prop:val;) declaration.

That's the crux. The pattern we are locking ourselves out of is just %foo: {...} bar: baz; being parsed as a declaration. That is such a ridiculously arcane pattern that I feel completely comfortable stating we'd never explore that space anyway, even if it did continue to be an option.

Notably, say in the future we decide that 1: red; should be a valid declaration. Currently that'll trigger nested-rule parsing, but the semicolon will cause us to stop parsing and throw it out as an invalid construct, then resume parsing fresh afterwards. If we changed the rules so that browsers parsed that as a declaration, then older browsers will... see it as invalid, and throw away tokens until the semicolon, then restart parsing fresh. In other words, we have precisely identical error-recovery regardless of how it's categorized in older browsers.

@Loirooriol
Copy link
Contributor

starting a declaration with a symbol is already very likely off the table, given the prevalence of people using a random ascii symbol to "comment out" a property.

I'm not convinced by this, because 1) I don't see this statement backed by any data, and 2) a declaration preceded by a random symbol may stay as invalid even if we add a new feature that uses that same symbol.

Like, even if there is plenty of +width: 10px on the wild, we might be able to add a new future that does something special for e.g. +width+: 10px. Option 3 without lookahead closes that door.

@plinss
Copy link
Member Author

plinss commented Jan 11, 2023

A problem I have with the "it's only an error recovery problem" approach, is that once something new gets added to selectors or properties, it's closed off forever in use for the other case. For example, if we add % as a special prefix for properties, we can never use it as a combinator (or vice versa). And that's not even considering cases we're already closing off, e.g. IIRC there's a proposal for extending list properties like: +backrgound: green;, kiss that goodbye before it's even properly considered.

I still feel that's too constraining. Paraphrasing as I believe @Loirooriol said elsewhere, we are bending and constraining the language here in ways that are restrictive, and introducing new (and seemingly arbitrary to the non-initiated) rules that authors have to learn and follow, all for the benefit of avoiding a single character. (And if we chose a mandatory & prefix, it just choosing a different character.) I just don't see the benefit being worth the cost.

And frankly, I don't think the copy/paste argument has all that much merit. As the proposal stands, authors cannot 'simply' copy paste rules into a nested context because they will have to manually scan them for the cases that need fixups, this will be error-prone. Big picture, I don't think we're really helping authors here. If authors have to add a simple prefix, that can be easily automated by tooling.

Other solutions that satisfy my concerns that I'm not sure have been properly considered are creating a nested rule context within an existing style rule, e.g.:

foo {
  color: red;
  @nest {
     bar { color: blue; }
     baz { color: green; }
  }
}

Which could be simplified to:

foo {
  color: red;
  @ {
     bar { color: blue; }
     baz { color: green; }
  }
}

or even:

foo {
  color: red;
  {
     bar { color: blue; }
     baz { color: green; }
  }
}

A solution like the above does simplify copy/paste and avoids all the syntax rules and extension issues. (It also doesn't preclude allowing @ bar { ... } for individual nested rules.)

@jensimmons
Copy link
Contributor

starting a declaration with a symbol is already very likely off the table, given the prevalence of people using a random ascii symbol to "comment out" a property.

I'm not convinced by this, because 1) I don't see this statement backed by any data

I worked as a lead front-end dev in China for three months, in two cities with two development different teams. And it was mind-blowing for me what they were doing in their CSS. It was so different than what I was used to, even though I'd already worked with many dozens of different teams, on hundreds of projects, in multiple countries across Europe and North America, over two decades. And yes, I saw code that had random ASCII symbols all over the place to comment things out, or make them work one way for one version of IE while another way for another version of IE. The experience taught me there's an incredibly wide variety of how people write their CSS. Especially given how many web developers do not speak English — there's a lot of diversity and variety in what's considered "best practice" in one community / country / continent vs another.

@Loirooriol
Copy link
Contributor

@plinss That other solution was discussed in #4748, even initially approved in #4748 (comment), but reverted in #4748 (comment). IIRC the concern was that it uses 2 levels of indentation, which can be inconvenient when having multiple levels of nested rules.

I guess I would prefer it over option 3 (which yeah, I feel like it's bending the language too much for little gain), but postponing the brackets instead of nesting them (i.e. option 4) avoided the double indentation so it was probably better.

@jensimmons I don't doubt that there are some people doing this kind of things, but I lack numbers to know if these are only some anecdotical cases, or if the breakage of adding a feature mixing symbols with declarations would be huge. Also, there might have been people using -- to comment out a declaration, but this didn't prevent custom properties since the effect is not observable unless you use var() or JS APIs. So I'm not convinced that adding such new features is "very likely off the table" as Tab said.

@plinss
Copy link
Member Author

plinss commented Jan 11, 2023

I accept that using a nested block looks weird when the outer most rule is only a nesting container due to {{ ... }}, but for that case we can always also accept the top-level @nest syntax. I'm not convinced the extra level of indentation should be a deal-breaker (it certainly isn't worth adding the language constraints just to avoid IMO).

I understand that alternative approaches were discussed and rejected in the past, but it's not clear that all of those decisions were made with the same information as we now have. I strongly suspect some of those would have gone differently were we making them now. If we're going to get past this impasse we all need to be able to take a step back and look at the big picture.

I fear that many of the advocates of the current approach have gotten there by a long series of compromises trying to narrow down the options, which each may have made sense in isolation, but when taken in as a whole have led us to a solution where the costs outweigh the benefits.

@jensimmons
Copy link
Contributor

I lack numbers

A Google search for "CSS star hack" returns 9.8 million results.

@plinss
Copy link
Member Author

plinss commented Jan 11, 2023

I lack numbers

A Google search for "CSS star hack" returns 9.8 million results.

It only returns 1660 results if you quote the phrase. And the majority of those talk about specifically targeting IE7 and below and are 9+ years old

@yisibl
Copy link
Contributor

yisibl commented Jan 12, 2023

With all due respect, @ is too much hack.

And yes, I saw code that had random ASCII symbols all over the place to comment things out, or make them work one way for one version of IE while another way for another version of IE.

@jensimmons As a Chinese developer, I'm curious about what kind of CSS, do you have an example?

@tabatkins
Copy link
Member

I fear that many of the advocates of the current approach have gotten there by a long series of compromises trying to narrow down the options, which each may have made sense in isolation, but when taken in as a whole have led us to a solution where the costs outweigh the benefits.

This is not the case, and speculation of this sort isn't helpful. I know exactly what the costs are in aggregate (I laid them out in my last comment), and believe they are more than acceptable vs the costs of using a syntax that diverges from the common usage of nesting across more than a decade of preprocessors (and possibly introduces additional levels of indentation to every usage of nesting).

I know you disagree, @plinss, but if my previous post hasn't convinced you I'm not sure anything else will. I personally am not going to be convinced to go back to a mandatory prefix or additional nesting, either, and there's no middle ground between our two positions to make a compromise possible, so I suggest you go ahead and file your objection if you're going to.

@LeaVerou
Copy link
Member

LeaVerou commented Apr 6, 2023

@plinss Thank you for clarifying. I seem to recall several times when the WG debated these @rule-based syntaxes, and we always resolved against them, even when the alternative was option 3, which is sigificantly worse than what is currently possible. Why do you think another discussion will resolve differently, now that the alternative is better? Is there new data that might contribute to a different decision?

@plinss
Copy link
Member Author

plinss commented Apr 6, 2023

I'm not asserting that the WG will resolve in favor of an at-rule based approach, or even seriously trying to bring about that outcome (though I do currently favor it slightly). I did propose the look-ahead approach after all, and fought hard to make it happen, so I am obviously fine with it.

My concern is that a non-at-rule based approach has long-term ramifications, there are language constraints and author foot-guns still (though much smaller ones than we had before). And I'm not convinced that all the WG members fully understood those during the previous decisions. As I said above, when I mentioned some of them in calls, there was surprise, so it's obviously new data to some that may have changed the prior outcomes, and is therefore cause to at least re-confirm the prior decisions in light of this new data.

I really just want affirmative consent from the WG, given the current understanding of all the costs before we continue down the current path. When judging those costs, I feel it's essential to consider them in light of an alternative approach, because this isn't a case of 'look-ahead or nothing', we do have another option and nothing us is stopping us from taking it except ourselves.

At the end of the day, if we do an at-rule based approach now, we can always add the look-ahead approach later and make the at-rule optional. (I'd also feel a lot more comfortable making that call later when things have settled down and emotions and stakes aren't running as high as they are now, making decisions under pressure tends to run towards bad outcomes.) Once look-ahead ships (for real, with WG consent), we can never walk it back if we later find the costs are too high and will be stuck with them for the foreseeable future.

As I said, once again, parser changes are dangerous, we need to treat them with care. While an at-rule solution won't make as many people happy today, it's a lot safer, won't potentially cause problems down the road, and doesn't preclude us taking the next step later.

@FremyCompany
Copy link
Contributor

FremyCompany commented Apr 8, 2023

FWIW, I also do not think an at-rule approach has any future. The fact it was rebuked in the working group several times is not a cause of this, but just a symptom of the real cause. The whole point of the nesting feature is to be easier to type and maintain than repetition, so adding an extra indentation level and a sizeable prefix will get a strong opposition from authors, because it's defeating the point of the feature. They will continue to use a module like SASS or LESS or SCSS to compile their code because they will offer a better alternative. If we do not provide authors with a solution at least as elegant as these engines, we might as well not provide anything.

The look-ahead approach, while much better than option 3, still has some issues, namely:

  • Requires parser changes - these have bitten us in the past more often than not and must not be taken lightly.

I would argue that the parser changes proposed here are marginal, and will not affect current authors at all.

  • Still has some restrictions on future syntax, they are much smaller than option 3, but they exist.

Not being able to add a top-level bracket in a css property value in a position other than the first. This is not a real restriction, we would not consider this at all. I would probably argue that we should never introduced top-level brackets in css property values, this is un-css and confusing. We should at the very least always wrap that in a function.

  • Has issues with error recovery. Since declaration recovery and rule recovery differ, unrecognized rules in declaration blocks will eat the following declaration. This will surprise authors.

Do you have an example?

  • We still need to define feature detection somehow.

I agree, but this is orthogonal. There is currently no way to detect the support of an at-rule either.

  • The syntax, while SASS-like, doesn't have quite the same behavior.

I am not that familiar with SASS, but can someone explain what those differences are?

@plinss
Copy link
Member Author

plinss commented Apr 8, 2023

The whole point of the nesting feature is to be easier to type and maintain than repetition, so adding an extra indentation level and a sizeable prefix will get a strong opposition from authors, because it's defeating the point of the feature

The repetition we save is in the selector list, which can be huge, that doesn't change with an at-rule or any other required prefix. Adding an & wasn't seen as an unacceptable burden, I don't see why 4 extra characters would make it so. Extra indentation isn't necessary (may be desired in some cases) but hardly defeats the point of nesting. That's a bit hyperbolic. Also, @nest isn't all that large as far as at-rule names go, we could even make it shorter if 5 characters is an untenable burden at the cost of readability. (I wish we could use a bare @ but older browsers don't treat that as an at-rule.)

There are also multiple forms an at-rule approach can take, and as I said, we can support several or all of them simultaneously.

For example:

  1. @nest [selector-list] { [declaration-block] }, allowed inside declaration blocks. No extra indenting.
div {
  background: blue;
  @nest span {
    background: green;
  }
  @nest b {
    background: yellow;
  }
}
  1. @nest [selector-list] { [list-of-nested-rules-only] }, allowed at top level only. Adds potential indenting for primary rule declarations.
@nest div {
  {
    background: blue;
  }
  span {
    background: green;
  }
  b {
    background: yellow;
  }
}
  1. @nest { [list-of-nested-rules-only] }, allowed inside declaration blocks only. Adds potential indenting for nested rules.
div {
  background: blue;
  @nest {
    span {
      background: green;
    }
    b {
      background: yellow;
    }
  }
}

All of the above provide author flexibility and avoid the mixed rules and declarations problem.

I would argue that the parser changes proposed here are marginal, and will not affect current authors at all.

The overall concern about parser changes isn't about impact to authors, it's about impact to the language. The real risk is always things we're not foreseeing now that will come around and bite us later when we try to add something new.

Do you have an example?

See above and several other conversations about how declaration error recovery and rule error recovery differ. By putting rules in a place where declarations are expected, we run the risk of using the wrong recovery mode, which can eat valid following declarations and lead to site breakage in ways that will surprise authors.

The primary benefit of an at-rule approach is that all browsers that ever supported CSS drop into rule recovery mode when they see an at-rule in a declaration block, so there are no side-effects or surprises to authors. It's been the extension mechanism from day 1, and we're proposing to not use it.

I agree, but this is orthogonal. There is currently no way to detect the support of an at-rule either.

It's orthogonal, but shipping nesting without feature detection makes the nesting feature useless for anyone who cares about supporting older browsers, especially during the transition phase as the feature rolls out and isn't universally available (we really don't want to encourage 'best viewed in X' again, do we?). Authors will either ship only nested stylesheets and break their sites for older browsers; ship both, making the user pay unnecessary download costs (violating one of the TAG's ethical principles); or just use a transpiler and ship un-nested stylesheets like they aready do today, and we don't need to bother with the feature.

@supports (@nest) or @supports at-rule(nest) would be trivial to add and obvious to authors. We currently don't have a good answer how to feature detect the look-ahead version. So this is a factor to consider.

@FremyCompany
Copy link
Contributor

Authors will either ship only nested stylesheets and break their sites for older browsers; ship both, making the user pay unnecessary download costs (violating one of the TAG's ethical principles); or just use a transpiler and ship un-nested stylesheets like they aready do today, and we don't need to bother with the feature.

Even if you could detect support client-side with @support (@nest) it does not change this equilibrium. You either ship the code twice, or you don't ship either version at all. Or you ship the legacy one in an @import which makes legacy browsers download more and have more latency. There is no way to win, here.

But this is nothing new. Javascript has had breaking syntactic changes all over the years. And, yes, for a while, you have to rely on UA sniffing to decide wether to ship the (shorter) modern code or its desugared version. Authors have been sucessfully doing this for years now. There is little downside to getting this wrong, too. Your site will work in both modes, so at worst you are missing out on saving some network bytes on a browser that does support nesting but you weren't aware of.

At the current rate at which browsers ship, in less than 5 years, 99.9% of browsers will support nesting natively and you will no longer need the transpiler at all. Just like everyone feels free to use ES5 today.

@astearns
Copy link
Member

astearns commented Apr 10, 2023

With my chair hat off, I am not convinced that we have enough new information to reconsider a wide range of previous resolutions on nesting. The main new information we have is that look-ahead is viable, which to my mind only strengthens the option 1->3->look-ahead evolution. It was consistently preferred (flaws and all) over other proposals, and the look-ahead improvement is likely to increase that preference.

My impression is that we have discussed error recovery issues, restrictions on future syntax, differences between our nesting and SASS, and the perils of changing parsing. Aside from how long it took to get someone to investigate parsing changes, I think the current proposal has been adequately defended against those challenges. I am not aware of new information on any of these that would change my mind, at least.

I am concerned about adequate feature detection, and I am still unclear how authors are meant to use the current proposal in projects that support pre-nesting browsers. But I believe this is a problem for all of the alternatives I have seen.

All this to say I don’t yet see enough evidence in this issue that we should change course. That’s just my personal opinion, and of course I welcome attempts to change my mind.

With my chair hat back on, I am going to move the question of whether the current draft should be updated to the look-ahead-enabled syntax. Since both of those options do mix properties and selectors, that question is I think separable from this issue. I have added a comment to 7961 which seems like the right place for that resolution.

@plinss
Copy link
Member Author

plinss commented Apr 10, 2023

My impression is that we have discussed error recovery issues

If that's the consensus, then so be it, I'll stop complaining, but before we get there, let me point to evidence that error recovery at least hasn't been fully considered in past decisions. See in this thread alone: @FremyCompany asking for examples of the error recovery problem (indicating he's not intrinsically familiar with the issue), yet expresses a strong bias against at-rules; Tab (who I know fully understands the issue), and myself both still getting error recover behavior wrong during conversations; several people expressing surprise during relatively recent calls about the error recovery and syntax restriction issues (well after at-rules were rejected).

My argument is that sufficient evidence exists that all the factors weren't taken into account during previous decisions to warrant at least a 5-minute overview of the relative costs and benefits of the two approaches and a simple sanity-check resolution, confirming we all know what we're buying into. Once again, I'm not advocating against adopting the look-ahead behavior, I just want us to do it with our eyes open and decisions made properly.

If the choice were simply a mandatory @nest prefix or not, with no other issues or consequences, I wouldn't even be raising this, of course we wouldn't require the prefix. But the choice is between look-ahead, which has other costs and issues, and @nest that's slightly more verbose, but has no other issues.

@plinss
Copy link
Member Author

plinss commented Apr 10, 2023

And, yes, for a while, you have to rely on UA sniffing to decide wether to ship the (shorter) modern code or its desugared version.

You're not seriously suggesting UA sniffing is the proper way to deploy this feature, are you? I'm somehow thinking that's not going to pass TAG review.

One could argue client hints would be appropriate, but then work needs to be done to specify and implement that.

@LeaVerou
Copy link
Member

LeaVerou commented Apr 10, 2023

And, yes, for a while, you have to rely on UA sniffing to decide wether to ship the (shorter) modern code or its desugared version.

I suspect that rather than UA sniffing, authors will just wait a bit until Nesting is supported in a reasonable percentage of browsers, then detect it client side and load an additional stylesheet only for those browsers that don't support Nesting. I believe the styling you get from a stylesheet that uses Nesting in an older browser is a proper subset of all the rules, so that would be a largely smooth progression, it would just involve 2x the download for older browsers, which is a commonly acceptable tradeoff once the set of nonsupporting browsers for a feature becomes small enough. In fact, build tools may even evolve to only ship the nested rules rewritten, so they could work as supplementary and not load the root rules twice (though this may have different results due to rules being out of order, but perhaps the tools would be smart enough to detect that).

@romainmenke
Copy link
Member

romainmenke commented Apr 10, 2023

I don't want to take this thread even further of topic because the focus here isn't how authors will deal with the transition period, but there are too many inaccuracies here :)


#8249 (comment)

But this is nothing new. Javascript has had breaking syntactic changes all over the years. And, yes, for a while, you have to rely on UA sniffing to decide wether to ship the (shorter) modern code or its desugared version. Authors have been sucessfully doing this for years now.

This isn't exactly true.
Very few people roll their own UA sniffing.
Most ship a single bundle targeted at the oldest browsers they need to support.

Others rely on services like polyfill.io which abstract away the UA sniffing.
UA sniffing is a very complex problem to solve because browsers lie, have bugs and because of recent privacy preserving changes.


#8249 (comment)

At the current rate at which browsers ship, in less than 5 years, 99.9% of browsers will support nesting natively and you will no longer need the transpiler at all. Just like everyone feels free to use ES5 today.

This is not true.
Not even flex has 99.9% adoption and that shipped 10 years ago.


#8249 (comment)

just use a transpiler and ship un-nested stylesheets like they aready do today, and we don't need to bother with the feature.

Authors don't want to use tools for anything. If nesting never ships it will also never reach the point when tools become unneeded.


#8249 (comment)

I suspect that rather than UI sniffing, authors will just wait a bit until Nesting is supported in a reasonable percentage of browsers, then detect it client side and load an additional stylesheet only for those browsers that don't support Nesting. I believe the styling you get from a stylesheet that uses Nesting in an older browser is a proper subset of all the rules, so that would be a largely smooth progression, it would just involve 2x the download for older browsers, which is a commonly acceptable tradeoff once the set of nonsupporting browsers for a feature becomes small enough.

Authors typically do not like a change that will both slow down their project for end users and add to the complexity of their stack. Even when it only causes perf issues for users on older browsers.


How authors will deal with the transition period is not the issue imho.
This is a solved problem.

Nesting is just syntactic sugar, so authors don't lose out on much by transpiling.

They will simply continue to transpile with existing tools and it will be rare for anyone to actually ship nested css. They will continue to do this for a long time because the benefits of transpiling will continue to outweigh the drawbacks.

This is not a bad thing.
There simply already is a trivial way for authors to write standard/native css and support the older browser version that their project requires.

@LeaVerou
Copy link
Member

I feel we need a new thread to discuss how authors will handle the transition period, and what we can do to improve that experience.

But, some replies to @romainmenke above:

This is not true. Not even flex has 99.9% adoption and that shipped 10 years ago.

It has 99.23%, which is pretty close.
And authors do use Flex (and grid) without shipping alternatives. They don't generally need features to reach 99.9% support to use them without backup, anything over ~93% or so tends to be considered good enough for that in my experience.
(and let's not forget that even font-size only has 96% (!))

Authors don't want to use tools for anything. If nesting never ships it will also never reach the point when tools become unneeded.

I'm a bit confused at this. The rest of your comment seems to be making the point that authors will simply never use native Nesting and will just continue to preprocess until the end of time. Here you're saying authors don't want to use tools for anything. Will they, or won't they use tools to transpile Nesting?

Authors typically do not like a change that will both slow down their project for end users and add to the complexity of their stack. Even when it only causes perf issues for users on older browsers.

I disagree.

  • If this were true, nobody would be using polyfills, which are regularly much slower than writing code without the new technology that is being polyfilled in the first place. With polyfills one typically exchanges speed in modern browsers and codebase simplicity for slowness in older browsers, and this is a tradeoff I've seen authors make over and over.
  • In my experience many (not all) authors do see value in being able to ship their code without needing build tools, and Nesting for many authors is the last remaining reason to preprocess CSS. Even if they need to use build tools to support older browsers, it's a markedly different paradigm than using build tools for code to work, anywhere.
  • Not every consumer of these technologies is a user facing website. E.g. this also means that libraries can offer a lighter bundle for projects that don't need to support older browsers, and a heavier one for those that do.
  • Being able to iterate on untranspiled code speeds up prototyping quite significantly, even if the code will eventually be transpiled in production.

@romainmenke
Copy link
Member

romainmenke commented Apr 10, 2023

@LeaVerou I think the tone/intent of my comment got lost.
I think we are saying similar things.

I feel we need a new thread to discuss how authors will handle the transition period, and what we can do to improve that experience.

Yes, that would be better than taking this further of topic :)


And authors do use Flex (and grid) without shipping alternatives. They don't generally need features to reach 99.9% support to use them without backup

The incorrect statement was that any feature would reach 99.9% in five years.
If numbers are used to back things up, it is important that these are somewhat accurate.

I didn't state anything about what 99.9% or any other level of support means for CSS authors, only that 99.9% in five years will be extremely unlikely.


Authors don't want to use tools for anything. If nesting never ships it will also never reach the point when tools become unneeded.

I'm a bit confused at this. The rest of your comment seems to be making the point that authors will simply never use native Nesting and will just continue to preprocess until the end of time. Here you're saying authors don't want to use tools for anything. Will they, or won't they use tools to transpile Nesting?

This was in response to :

Authors will either ship only nested stylesheets and break their sites for older browsers; ship both, making the user pay unnecessary download costs (violating one of the TAG's ethical principles); or just use a transpiler and ship un-nested stylesheets like they aready do today, and we don't need to bother with the feature.

Arguing that the tools required during the transition period make the entire feature redundant doesn't make sense, exactly for the reasons you listed.


Authors typically do not like a change that will both slow down their project for end users and add to the complexity of their stack. Even when it only causes perf issues for users on older browsers.

I should have elaborated a bit more here.

If we imagine that your proposal is supported by tooling, authors will have two choices :

  1. produce a single, transpiled stylesheet during the transition period
  2. produce two stylesheets, one for modern and one for older browsers during the transition period

Option 1 doesn't require CSS Authors to make any other changes to their project. Simply pass the stylesheet to whatever tool that can desugar nesting and what comes out will work everywhere. After the transition period the transpiling tool can be disabled/uninstalled.

Option 2 requires CSS Authors to:

  • add JavaScript to dynamically load the right stylesheet (might also require HTML changes)
  • change their tooling to produce two stylesheets with two different configs
  • take the performance hit on older browsers
  • undo all changes after the transition period

Option 1 is simpler and given that nesting is purely syntactic sugar there are few drawbacks to transpiling during the transition period.

Most transpiling tools make it trivial to skip certain transforms during active/local development. Which give the benefits of rapid prototyping as you mentioned.


If this were true, nobody would be using polyfills, which are regularly much slower than writing code without the new technology that is being polyfilled in the first place. With polyfills one typically exchanges speed in modern browsers and codebase simplicity for slowness in older browsers, and this is a tradeoff I've seen authors make over and over.

The choices I am weighing are :

  • transpile for everyone, everything works and is fast everywhery
  • transpile for some, everything works but only fast for some (although this group grows to near 100% over time)

When the second option is also more complex to setup, it doesn't make much sense to go down that road purely for the transition period.

Some authors might chose to do so, and that is fine.

My argument was not that other strategies are invalid, only that a simpler alternative already exists : transpile for everyone for as long as required for a given project.


When I mention transpile or transpiler I am never talking about Sass, only about tools that aim to desugar standard css nesting.

@astearns
Copy link
Member

Perhaps we can move the transition discussion to #8399? Or should it be a completely new issue?

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed [css-nesting] Problem with mixing properties and selectors, and agreed to the following:

  • RESOLVED: Close no change
The full IRC log of that discussion <fantasai> scribenick: fantasai
<fantasai> astearns: We have this one issue, so I want to set aside the question of feature detection and down-compat
<fantasai> ... and also set aside question of Option 3 vs other SASS-like syntaxes
<fantasai> ... and go directly to, are we on the right path on a SASS-like syntax
<fantasai> ... or should we consider some other type of syntax?
<fantasai> astearns: What I would like to do is look at the argument being made in this issue around the drawbacks of a SASS-like syntax
<fantasai> ... and make the strongest case that we can, without arguing against anything yet, without coming up with counter-arguments, just going with the strongest argument we can for "we're on the wrong path" and see if anyone on the call agrees we should be looking at alternatives at this point
<fantasai> ... plinss, does this sound like a fair way forward?
<fantasai> plinss: yes, but we have to discuss the drawbacks of existing SASS
<fantasai> astearns: I'm suggesting we identify the drawbacks, but don't argue them
<fantasai> ... come up with the strongest presentation of the drawbacks, before we tear them apart
<fantasai> ... no no counter-arguments yet
<fantasai> astearns: Issue is about SASS-like syntax vs something else (such as an at-rule)
<fantasai> ... plinss has identified 4 drawbacks for a SASS-like syntax
<fantasai> astearns: Issues with error-recovery
<fantasai> astearns: Restrictions on future-syntax
<fantasai> astearns: Doing something SASS-like, but not actually SASSy (concatenation)
<fantasai> astearns: Ideal syntax requires changes to parser model
<fantasai> astearns: With that summary, is there anything someone wants to add that would strengthen this list of concerns?
<fantasai> plinss: Want to clarify my position
<fantasai> ... I didn't like the proposed direction
<fantasai> ... but because I have concerns
<fantasai> ... I like how we're going, but I also think the at-rule approach has merits because it doesn't have the drawbacks
<fantasai> ... My other concern is that, I think we look at both issues, and we've said "it's not great but it's not that, but if it's an at-rule or SASS-like, we chose SASS-like"
<fantasai> ... I'm not sure we've actually looked at all the issues together, and asked, in aggregate, are we still on the right path
<fantasai> ... Rather than looking at each decision in isolation
<fantasai> ... I think the issues are manageable, any one of them is not a reason to reject; but together might be enough
<fantasai> ... I'm leaning towards at-rule because it's safer
<fantasai> ... once we go down path of SASS-like syntax, we're stuck with its drawbacks forever
<fantasai> astearns: Of everyone on this call, is there anyone who has the same concerns?
<plinss> https://github.com//issues/8249#issuecomment-1496776853
<fantasai> SebastianZ: Thread is long, can we point to the comment summarizing the concerns?
<fantasai> astearns: We can get into that, but we risk running into an isolated argument
<fantasai> SebastianZ: I can see the point that plinss is outlining
<fantasai> ... these are problems
<fantasai> ... and error-recovery is the most important one
<TabAtkins> q+ about error recovery
<fantasai> ... which would be no problem if we went the at-rule route
<TabAtkins> Zakin, shut up
<fantasai> plinss: Just want to confirm that everyone understands the issues, e.g. what do I mean by error-recovery problem
<fantasai> astearns: OK, let's going to details of error-recovery
<fantasai> ... but keep going with approach of making the strongest possible case
<fantasai> astearns: In my opinion, the worst bit of error-recovery problem is, the current proposal allows for rules to be dropped in error-recovery in a mixed selector-and-property syntax
<fantasai> ... that would not otherwise be dropped
<fantasai> ... so the order in which you declare your properties and nested selectors
<fantasai> ... can cause parts of the stylesheet to be ignored
<fantasai> plinss: If you have a rule that's dropped, it can eat a following declaratoin
<fantasai> ... normally within a declaration block, we're in declaration recovery
<TabAtkins> q+
<fantasai> ... if we mix with rules, they have different error-recoery behavior
<astearns> ack TabAtkins
<fantasai> ... if you're recovering from a declaration, but you're parsing a rule, you're going to eat the next declaration
<fantasai> TabAtkins: went through details of error-recovery
<fantasai> ... if talking about eating of things unexpectedly, there are two potential ways
<fantasai> ... One is an old browser seeing nesting code
<fantasai> ... firstly, this will wreck your stylesheet anyway
<fantasai> ... You can construct an artificial scenario where optional things are nested, but it's very narrow and strange
<fantasai> ... usually necesary rules are written there, if you lose them your page is broke
<fantasai> ... The fact that the following declaration might get eaten in addition to rules being dropped, you have a problem anyway
<fantasai> TabAtkins: the other concern is in a browser that does understand nesting, what can happen if you have invalid rule followed by a declaration
<fantasai> ... or invalid declaration followed by a rule
<fantasai> ... details in the post
<fantasai> ... but with parsing change that's already in the Syntax spec
<fantasai> ... where a nested rule -- if you see a semicolon in the prelued (before {}), we immediately stop and throw it out
<fantasai> ... with that change, it's a stable, predictable amount of things being thrown out
<fantasai> ... if we parse an invalid rule, we read until we get to the semicolon after the rule
<fantasai> ... restart, try to parse as a rule, and then [missed]
<fantasai> ... The other way around, invalid declaration followed by invalid rule
<fantasai> ... we first parse until invalid declaration ends (;) , then restart as a rule but abort on the semicolon again anyway
<fantasai> ... and then parse the rule afterwards
<fantasai> ... There's a small corner-case around custom properties, because you can put anyting in them and might have something that looks like a rule inside, or [missed2]
<fantasai> ... but even an at-rule based syntax will interfere with custom properties in that way, so either way we have a problem
<fantasai> ... if you do something weird enough
<fantasai> TabAtkins: so in a nesting-capable browser, there's very little possibility of eating a following declaration by accident
<fantasai> ... and in nesting-incapable browser, you have major problems anyway; and you should be putting your declarations at the top anyway, which avoids all such problems
<fantasai> astearns: wanted to avoid counter-arguments ...
<fantasai> ... SebastianZ, enough explanation?
<fantasai> SebastianZ: yes
<fantasai> plinss: I'd like to counter
<fantasai> ... Nothing Tab said that's incorrect, except we differ on relative importance
<fantasai> ... Obviously if someone buys into nesting and they go all-in, yes the entire stylesheet is b0rked and need not go into details
<fantasai> ... but CSS is designed for progressive enhancement
<fantasai> ... a lot of websites, it isn't a single person writing a stylesheet; all aggregated together
<fantasai> ... you might have one person sprinkling a little nesting here and there
<dbaron> Scribe+ dbaron
<fantasai> ... and they are very likely to not read the spec and know that nested rule should go last
<fantasai> ... and might end up dropping a significant amount of a declaration
<jensimmons> q+
<fantasai> ... and it's also entirely possible that they won't see that, because they're on a modern machine, and not on old low-powered device
<TabAtkins> Again the nested rule is *also* getting dropped. Page is already broken.
<fantasai> ... so I think the likelihood is higher than Tab thinks
<fantasai> plinss: Wrt browsers that do support nesting, I agree that the current approach is robust except wrt custom properties
<fantasai> ... my concern is what happens in the future? If we want to add some new capability, new combinator or other strange syntax
<fantasai> ... might restrict ourselves from what we'd do otherwise, or have a risk of some problems
<astearns> ack fantasai
<fantasai> astearns: that's example of how things are tangled up
<dbaron> fantasai: I wanted to address question of downlevel clients and progressive enhancement
<dbaron> ... I think authors will adapt practice of putting nested rules after declarations, generally what they do already. Not too concerned about that case.
<dbaron> ... Usually not going to be doing this in progressive enhacement way, and if so follow best practice.
<dbaron> ... more likely to see nested rules inside of @-rules.
<dbaron> ... unlikely to see progressive enhancement of bare nested rules followed by a declaration. Not too worried about that case.
<matthieudubet> q+
<fantasai> astearns: when I see ppl using PostCSS examples, I immediately found declarations following after rules, it's common
<fantasai> plinss: I agree the risk is small, percentage is low, and web is vast
<fantasai> ... can still affect millions of people
<astearns> ack jensimmons
<fantasai> jensimmons: I have a question, because even though this issue is very long, there's not a simple, clear explanation that I could find of what gets eaten.
<fantasai> ... so here's the question
<fantasai> ... could someone very simply explain what gets eaten?
<TabAtkins> here's the maximum dangerous situation: `<new-wacky-property-syntax>: {...} more-stuff;`. If they write this invalidly, or use in a Nesting-capable browser that doesn't understand the new syntax, what's the maximum damage?
<fantasai> ... perhaps focused on borwsers that do support nesting
<fantasai> plinss: in a browser that does support nesting, very little chance of things getting mis-eaten, except custom properties
<fantasai> ... bigger concern is down-level clients
<fantasai> ... becaue what gets eatin is a rule and the following declaration
<fantasai> ... if I start a rule, followed by a declaration, and the browser doesnt' understand that the rule is a rule and parse it as such
<fantasai> ... it will go into declaration error-recovery, and eat the rule *and* the next declaration (up to the semicolon)
<fantasai> jensimmons: And in browsers that do support nesting, something that gets eatn?
<matthieudubet> q-
<fantasai> astearns: only in custom properties where the custom property value is using a brace
<fantasai> jensimmons: So if using nesting, and the thing they nest is something that doesn't make sense e.g. mispell the selector
<matthieudubet> q+
<TabAtkins> Damage is: since decl parsing failed, we restart as rule. We parse until the {}, and stop. Then we'll start parsing the stuff *after* the {} fresh. It's *theoretically possible* for this to be mistaken as a valid declaration or rule, rather than the suffix of an invalid declaration. But as long as we (the CSSWG) only design top-level {}-in-declarations to be the whole value, this isn't a problem.
<fantasai> ... what happens to the rules after that nesting thing?
<fantasai> astearns: I believe we're ok. Malformed thing gets dropped, and in browser that supports nesting everything after the dropped rule is retained
<fantasai> ... right?
<fantasai> plinss: I don't think there's a situation where we drop a rule [...]
<fantasai> ... what gets dropped is a declaration that doesn't need to be dropped
<fantasai> jensimmons: in browsers that don't support nesting
<SebastianZ> q+
<fantasai> plinss: right. Also in browsers that do, but in that case much more of a corner case. But in downlevel browsers much more common
<fantasai> jensimmons: so in Nesting-supported browsers, would only have a problem in malformed case or a particular strange custom property value
<fantasai> TabAtkins: After nesting is supported, it's not possible to eat a following declaration after anything invalid
<fantasai> ... but if something is in valid, we might parse as a rule and the leftover stuff (that we didn't get to) could maybe be interpreted as a declaration
<fantasai> ... but we shouldn't need to introduce such constructs
<fantasai> plinss: Something that would have been interpreted as a preceding rule, you wind up with the tail end of that interpreted as another declaration or rule.
<fantasai> ... agree that's a corner case
<fantasai> plinss: In the future, we might end up introducing problems
<fantasai> TabAtkins: we need two restrictions, one which is already in the spec, to avoid that
<astearns> ack matthieudubet
<fantasai> matthieudubet: If we mandate in the nesting syntax to have declarations first, then style rules, so you can't mix, don't we get rid of the issues?
<fantasai> matthieudubet: since we know we can't mix, we don't have the issue
<fantasai> matthieudubet: this is similar to Option 4, two blocks, but you don't write the braces
<fantasai> matthieudubet: declarations first, and style rules after
<fantasai> plinss: There's no rule for behavior that will change existing browers
<fantasai> ... so even if we say it's invalid to put a declaration later, an older browser will be in declaration mode
<fantasai> matthieudubet: but there's less risk of this happening, because nobody would want to write such a thing (since not supported in new browsers either)
<fantasai> ... it's the same error-recovery, but you mitigate the risk of having this in actual style sheets
<jensimmons> q?
<fantasai> plinss: I think that's a valid approach... not sure that restriction on the SASS-like syntax is worth the benefit
<fantasai> ... but it is a viable path
<astearns> akc SebastianZ
<emilio> q+
<fantasai> SebastianZ: So if I understnad correctly, authors could put semicolon after the rule, and the next declaration wouldn't get eaten
<fantasai> TabAtkins: correct
<astearns> ack SebastianZ
<fantasai> SebastianZ: So just for clarification, one could use that to support all the browsers that don't support nesting
<jensimmons> q+
<fantasai> ... of course they're still skipping the nested rule, but at least we don't have the next declaration gettin eaten
<astearns> ack emilio
<fantasai> plinss: We could mandate a semicolon after nested rules, to force doing that everywhere
<fantasai> emilio: I think I like the declarations to be forced before
<fantasai> ... especially since the behavior of interleaving is the same as if they were sorted before anyway
<fantasai> ... if that satsifies everyone, then I think it's best
<fantasai> ... mostly because that way we don't have the weird problem of explaining
<fantasai> ... you put this after the nested rule, but the browser created an anonymous rule that put all teh declarations first
<fantasai> ... and acts as if you had written it before
<fantasai> ... so I think that might be nice
<TabAtkins> that's the parser switch that all the impls hated before...
<astearns> ack jensimmons
<fantasai> +1 emilio, this clarifies the cascade
<fantasai> jensimmons: I dont' like the idea of requiring that declarations go before nested rules
<fantasai> ... like plinss says, people jam CSS into things all over the place
<fantasai> ... it will make things less useful
<emilio> q+
<fantasai> ... and I always prefer to go for the better choice long-term and deal with limitations short-term when redesigning language
<fantasai> jensimmons: wrt transition, my sense is that majority of authors won't use Nesting for 3-4 years
<fantasai> ... those who do use it sooner, what I have been seeing is that they're using a preprocessor to do it
<fantasai> ... so writing their own CSS nested, and then using some automated stack to process it back out into old-school CSS
<fantasai> ... similar to using SASS
<fantasai> ... I think that might really take off, the tools ppl build for that will be popular
<TabAtkins> in particular, "no properties after rules" means at some point we need to decide we're "in rules". This requires some way of detecting "oh i tried to parse this as a prop but failed, looks like a rule" that won't misfire in weird cases.
<fantasai> ... and they will preprocess it for older browsers
<TabAtkins> the end result is actually *at least* as complex as today, possibly more
<fantasai> ... I don't think there will be an epidemic of ppl writing progressive nested rules, they're too lazy to do that
<fantasai> ... they already don't think about progressive enhancement nearly enough
<astearns> eck emilio
<fantasai> emilio: Reason I think this restriction is nice, not just for parsing, but let's say you don't know how nesting is specced
<astearns> q+
<TabAtkins> q+
<fantasai> ... you put media query inside and then more declarations at the bottom
<fantasai> ... that won't work like you expect
<astearns> ack emilio
<astearns> q--
<fantasai> ... because the declarations are shifted up, and in some cases not a problem but I'm sure it will confuse people
<fantasai> jensimmons: You mean, they dont' cascade as expected?
<fantasai> emilio: right
<fantasai> ... the rules inside the @media will be later in cascade order than the declarations outside @media but after it
<fantasai> ... I would find it confusing if I didn't know internally how it works
<fantasai> ... same for dropping bare declarations inside MQ and stuff, which we resolved they would be put into an anonymous rule at the front
<fantasai> ... if you don't know that they get moved, it's super confusing
<jensimmons> q-
<fantasai> ... that they apply as if they're at the top
<jensimmons> q+
<fantasai> ... so I think that would be a good restriction not just for the transition
<matthieudubet> yes it's also more obvious that the anonymous rule is after any declarations
<matthieudubet> than*
<fantasai> ... I think it's more understandable for anyone using nesting without knowing the details of the spec
<astearns> q- later
<fantasai> TabAtkins: no declarations allowed after rules is exactly a parser-switch of the kind the WG disliked
<fantasai> ... and there's two ways we could possibly do it
<fantasai> ... 1. We parse as today, you'll parse declarations properly but throw them out
<fantasai> ... but this means some garbage rule might be ????
<emilio> q+
<fantasai> ... 2. We do a stronger parsing switch, where we have a mode switch that changes how things are parsed
<astearns> s/garbage rule might be ????/garbage comment might be parsed as a rule/
<fantasai> ... this is more dangerous, might be possible to trigger this mode unexpectedly
<fantasai> ... and that's more complicated for us to be careful around in the future
<fantasai> ... so I don't think there's any actual benefit for instituting a parser switch
<astearns> q- later
<astearns> zakim, close queue
<Zakim> ok, astearns, the speaker queue is closed
<fantasai> TabAtkins: [something that went around too many times to capture]
<astearns> ack TabAtkins
<fantasai> plinss: I think we're getting off into the weeds of trying to mitigate these issues, all I'm asking for is a sanity check
<fantasai> ... if we look at all these issues, is it worth continuing down this path?
<fantasai> ... if so, we can continue to hash out the issues
<fantasai> astearns: Has anyone on the call been convinced that we should reconsider the path that we're on?
<astearns> ack jensimmons
<fantasai> ... if plinss is the only one, then perhaps we close this issue and open new issues about each individual small issue within the SASS approach
<fantasai> jensimmons: I think the fact that declarations that come after a rule are earlier in the cascade being earlier in the cascade
<fantasai> ... should add to the list
<fantasai> ... I'm more concerned about that that the other things
<fantasai> ... I don't believe we should throw out the declarations that come after the rules
<TabAtkins> ("declarations after rules" is an issue with any syntax, it's not specific to any one unless we totally prevent mixing syntactically)
<fantasai> ... I would prefer we investigate making the cascade *not* resorted
<fantasai> ... if that's absolutely impossible, then we have to teach it as "it's going to be confusing in the cascade, so sort to the top, this is the best practice"
<astearns> ack fantasai
<Zakim> fantasai, you wanted to support emilio's point
<jensimmons> q+
<plinss> q+
<astearns> ack emilio
<fantasai> emilio: I think the general approach we're taking is preferable as well
<fantasai> ... regarding Tab's comment
<fantasai> ... we have similar parser switches, e.g. @import rules not allowed after other rules
<fantasai> ... could easily implement as keep parsing as before, but throw out the declarations
<fantasai> ... user-wise, as a CSS author, I would prefer if this worked
<fantasai> ... and declarations were directly in the cascade
<fantasai> ... but if we're not doing that, which is also reasonable if we're concerned about perf or something, I think the restriction is not a huge deal
<TabAtkins> (note that Sass allows decls after rules, with exactly the same behavior as what we're specifying - all glommed together into the parent rule, preceding nested rules)
<fantasai> ... we can discuss in another issue at another point in time
<fantasai> astearns: I wanted to ask again, given the cluster of issues around the SASS-like syntax, are we convinced we're on the wrong path and should investigate alternative syntaxes?
<emilio> TabAtkins ugh, I think that's dumb :/
<fantasai> jensimmons: I think we're still going in the right direction, especially considering what we've heard from authors about what they want
<emeyer> I don’t know if we’re going the wrong direction, but I do think more investigation is needed.
<fantasai> astearns: My proposal is that we close this issue no change
<fantasai> ... and take each of these concerns and move them to other existing issues or new issues
<fantasai> ... so that we can work through solutions to these issues as much as we can in the framework we have
<emeyer> +1 to astearns’ proposal
<fantasai> ... would that be acceptable, plinss ?
<emilio> TabAtkins: but ok, I guess if authors are fine with that and sass doesn't have a lot of reports about that behavior... fine?
<fantasai> plinss: Yes. I just wanted us to look seriously at the big picture. Satisfied to go with the group consensus
<fantasai> ... But if we later find more issues, and suggest to go back and reconsider, we should reconsider
<fantasai> ... not say "despite new information, not going to reconsider"
<fantasai> ... at-rule we could deploy now, without working through these issues
<fantasai> ... but I'm not going argue this point anymore until new information comes up
<fantasai> astearns: proposed to clsoe this monster issue no change
<fantasai> ... and follow through on each individual issue on separate issues
<fantasai> ... any objections?
<fantasai> +1
<fantasai> RESOLVED: Close no change
<fantasai> ACTION: astearns to make sure smaller issues are followed up on
<fantasai> plinss: one other caveat, there might be someone else in the larger group that shares concerns, so maybe poll everyone?
<fantasai> astearns: I'll add a comment to the issue, here is what we resolved and why, and ppl can comment
<fantasai> plinss: I just want to make sure we make the right decision in the right way
<fantasai> INSERT replacing "ack fantasai" with -
<TabAtkins> new room topic?
<fantasai> fantasai: Stepping back to Plinss's question, I think we are on the right path. Considering developer ergonomics vs the downsides of this approach
<fantasai> fantasai: I think the best we can do is continue on this path and try to address the issues as we can
<fantasai> fantasai: I also wanted to support emilio's point about the cascade effects being confusing
<fantasai> fantasai: I think we should either make declarations after rules invalid (as emilio suggested) or sort them in the cascade as specified somehow (as jensimmons suggested)

@astearns
Copy link
Member

astearns commented Apr 12, 2023

Summarizing the resolution and discussion:

There are several minor issues with a SASS-style syntax for nesting we have identified so far. They include

  • Issues with error-recovery
  • Restrictions on future-syntax
  • Using SASS-like syntax, but not matching some SASS behavior
  • Parsing changes are risky
  • Unintuitive cascading behavior when declarations come after rules

We had consensus in the breakout session that even considering all of these issues together, we still plan on pursuing the SASS-style syntax. Working on solutions to these issues (where possible) will happen in separate issues.

But if there is anyone that was not in the breakout session who finds this set of issues a compelling reason to change course and NOT pursue SASS-style syntax, please do speak up here. And when new issues arise, we should take a moment to add them to what remains in this list as a checkpoint to reconsider whether the mass of minor issues has become too large.

@Loirooriol
Copy link
Contributor

I wasn't in the session. I think these issues are concerning, and I prefer the so-called options 1 or 4 which don't seem to have these problems. But I won't object to the current thing.

BTW, about "Using SASS-like syntax, but not matching some SASS behavior", have the SASS developers said anything about this? They have requested CSS changes in the past when there was a clash, like renaming @if to @when.

@SebastianZ
Copy link
Contributor

BTW, about "Using SASS-like syntax, but not matching some SASS behavior", have the SASS developers said anything about this? They have requested CSS changes in the past when there was a clash, like renaming @if to @when.

@mirisuzanne was on the call and didn't raise concerns regarding this, as far as I can tell. Though I may be missing earlier comments in which she expressed any concerns.

Sebastian

@plinss
Copy link
Member Author

plinss commented Apr 12, 2023

Two clarifications:

  1. The cascading behavior is an issue for either an at-rule or the SASS-style approach, so it shouldn't be part of the consideration here (I think). All of the other issues go away entirely with an at-rule approach.
  2. The proposal on the table wasn't to "NOT pursue SASS-style syntax" anymore, it was to not ship SASS-style syntax now. We have the option to ship an at-rule syntax now, and continue to refine the SASS-style approach over time, and then ship that when we feel it's ready. That effectively just makes the @nest prefix optional later (authors who prefer the explicit rule at-rule could still use it).

(And for those not on the call, I don't think any of the issues above individually are show-stoppers, it's just when you consider the complete list of the issues vs the advantages is when I start to have concerns. As with @Loirooriol above, it's not enough for me to object, but it was enough to go hmmm and ask the question.)

@LeaVerou
Copy link
Member

I wasn't in the call (got stuck in traffic) but I personally still think we are on the right track, and I'm not concerned about most of these issues.

However, I would also be fine with a syntax that mandates that declarations have to precede rules, as I think that's good authoring practice in general (and would make the backtracking needed even more efficient, as it only needs to be done max once per rule). We decided against an author-facing parser switch (i.e. syntax authors would have to use to invoke the other mode). An automatic parser switch managed by the browser as it encounters syntax would be fine by me, and seems very easy to teach. It is also very compatible with allowing them to be intermixed in the future. Reading the minutes, @jensimmons brought up a concern that this would restrict use cases, but did not elaborate further (or wasn't minuted doing so):

jensimmons: I dont' like the idea of requiring that declarations go before nested rules
... like plinss says, people jam CSS into things all over the place
... it will make things less useful

I was wondering what cases you had in mind?

Also, could someone explain this further?

Unintuitive cascading behavior when declarations come after rules

Is this that in cases like these:

.foo {
	color: red;

	& {
		color: green;
	}

	color: blue;
}

You'd expect the color to be blue, but it's actually green?

@jensimmons
Copy link
Contributor

@LeaVerou A discussion about "a syntax that mandates that declarations have to precede rules" needs to go in a new issue. This issue is only about whether/not we should stop moving forward with the current direction, and change course. Which we decided today on the call, no.

@astearns
Copy link
Member

OK, here’s where I think we should move subtopics from this issue:

Issues with error-recovery
-> #8349

Restrictions on future-syntax
-> #8251

Using SASS-like syntax, but not matching some SASS behavior
This has been discussed in a few issues like 2937 and 3748, where we have decided for the most part not to worry about this. If anyone is still concerned with the differences, please open a new issue.

Parsing changes are risky
-> #7961

Unintuitive cascading behavior when declarations come after rules
We have gone back and forth a few times on whether we should allow declarations after rules, and if we do how do we handle them (in the cascade and in CSSOM). I have not found a single issue that seems like an apt place to continue this discussion, so I think we should have a new issue on this.

@tabatkins
Copy link
Member

tabatkins commented Jul 14, 2023

Closing this issue, as it's been split into subtopics and generally resolved at this point.

(Hm, we don't have a great label for htis, so I'm gonna mark it as invalid, as I think that's closest to "no longer contains a relevant issue needing to be addressed".)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
No open projects
Development

No branches or pull requests