Re: [csswg-drafts] [css-cascade] [css-nesting] Figure out whether we're fine with "shifting up" bare declarations after rules (#8738)

The CSS Working Group just discussed `[css-cascade] [css-nesting] Figure out whether we're fine with "shifting up" bare declarations after rules`, and agreed to the following:

* `RESOLVED: We will address ths issue, and fix nesting to allow for bare declarations after nested rules without moving them above.`

<details><summary>The full IRC log of that discussion</summary>
&lt;fantasai> lea: Right now, if we have bare declarations after a nested rule, current behavior is that they're shifted up to be before the nested rule<br>
&lt;fantasai> ... which means nested rule can override them<br>
&lt;fantasai> ... [gives example in the issue]<br>
&lt;astearns> q?<br>
&lt;fantasai> ... This behavior violates source order when specificity is the same, and is against author expectations<br>
&lt;lea> https://github.com/w3c/csswg-drafts/issues/8738<br>
&lt;fantasai> ... WebKit ran a poll showing that<br>
&lt;fantasai> ... I ran two polls, here's link to both of them<br>
&lt;fantasai> ... Almost 80% of authors were expecting the different behavior<br>
&lt;fantasai> ... and those who didn't seemed to have a broken mental model around specificity<br>
&lt;fantasai> ... things like "@supports increases specificity"<br>
&lt;chris> that seems surprising, it breaks document order. I bet people spend time debugging this<br>
&lt;fantasai> ... That's quite dangerous, not just that this feature has a weird behavior, but it encourages a broken mental model of how CSS works<br>
&lt;fantasai> ... specificity is already confusing as it is, we don't need to add to that<br>
&lt;fantasai> lea: in terms of changing behavior, not really much reason<br>
&lt;fantasai> ... in the thread it's "this is how preprocessors work"<br>
&lt;fantasai> lea: in the TAG we have a principle against this<br>
&lt;fantasai> lea: other option is compatible with existing tools<br>
&lt;fantasai> lea: we suggest that ppl go with the usability benefit<br>
&lt;fantasai> lea: 10 years down the line, how preprocessors of today work will not matter<br>
&lt;fantasai> lea: There was also point that maybe slightly easier to implement current way<br>
&lt;jensimmons> q+<br>
&lt;oriol> q+<br>
&lt;emilio> q+<br>
&lt;fantasai> lea: but doesn't seem that there is serious implementation complexity problem with changing to match source order<br>
&lt;fantasai> lea: Also, jensimmons ran several more polls, which validated the same point that authors find the behavior confusing<br>
&lt;astearns> ack jensimmons<br>
&lt;fantasai> jensimmons: I feel pretty strongly that we should change the behavior so that it matches what people expect from CSS cascade, that later thing overrides earlier thing when specificity is tied<br>
&lt;fantasai> jensimmons: People will not remember what SASS did 20 years from now<br>
&lt;astearns> ack oriol<br>
&lt;fantasai> oriol: I think Lea posted the wrong link to the poll above...<br>
&lt;miriam> q+<br>
&lt;fantasai> oriol: I agree that we should not prioritize aligning with preprocessors, since preprocessors can always change by releasing a new version<br>
&lt;fantasai> oriol: authors can adopt when they want<br>
&lt;lea> comment with polls: https://github.com/w3c/csswg-drafts/issues/8738#issuecomment-1746990112<br>
&lt;fantasai> oriol: but this wasn't the main reason<br>
&lt;fantasai> oriol: The question is how do you handle this?<br>
&lt;fantasai> oriol: One was that we would just ignore declarations after nested rules<br>
&lt;lea> q?<br>
&lt;fantasai> oriol: but that seems problematic if they add garbage, and could cause declarations to stop working, so concerned about future-compat<br>
&lt;fantasai> oriol: Wrapping in &amp; doesn't work with pseudo-elements<br>
&lt;fantasai> oriol: so I don't think this is straightforward<br>
&lt;fantasai> oriol: While I agree that this is pretty bad and very confusing, and I would have objected to current syntax of nesting if I had realized this<br>
&lt;fantasai> oriol: I think alternatives seem worse<br>
&lt;fantasai> oriol: I don't see a clear proposal addressing all the concerns<br>
&lt;fantasai> oriol: I think the current state is the lesser of the evils<br>
&lt;lea> q+<br>
&lt;chris> unclear why current state is "worse"<br>
&lt;fantasai> astearns: I don't believe we're talking about discarding things after nested rules, only talking about how to keep them in and do the source order correctly<br>
&lt;fantasai> astearns: whether wrapping in an &amp; is the way forward, would need to work through the issues with pseudos etc.<br>
&lt;astearns> ack emilio<br>
&lt;fantasai> astearns: Let's go back to the queue<br>
&lt;fantasai> emilio: I also brought another concern which may or may not be an issue<br>
&lt;fantasai> emilio: this also assumes we go with wrapping-in-&amp;, which seemed like most straightforward solution<br>
&lt;fantasai> emilio: Wrapping stuff in extra rules can have surprising consequences perf-wise<br>
&lt;fantasai> emilio: you triple the amount of selectors that element has to match<br>
&lt;fantasai> emilio: I agree with Oriol that given the &amp; stuff doesn't work with pseudo-elements, we either need to figure out how to fix that<br>
&lt;fantasai> emilio: but current behavior is better than having some declarations work and others not<br>
&lt;fantasai> emilio: we want to make sure all the declarations work<br>
&lt;fantasai> emilio: but then the nested at-rule would also not work?<br>
&lt;fantasai> emilio: so maybe pseudo-elements issue isn't such a great argument, since the at-rule inside would also be broken<br>
&lt;fantasai> astearns: not sure I follow<br>
&lt;fantasai> emilio: You have sth::before { declarations; @rule {... }; more-declarations; }<br>
&lt;fantasai> emilio: The issue is that more-declarations gets shifted up above @rule<br>
&lt;fantasai> emilio: but wrapping in &amp; doesn't work, because :is() doesn't work with pseudo-elements<br>
&lt;fantasai> emilio: but actually you have this same problem with the at-rule<br>
&lt;fantasai> emilio: if you put bare declarations in the @rule, they also get magically wrapped i n&amp;<br>
&lt;fantasai> emilio: so maybe wrapping in &amp; isn't so terrible<br>
&lt;fantasai> emilio: it's weird if ones before work and ones after don't<br>
&lt;fantasai> emilio: but the @rule declarations would also be broken<br>
&lt;astearns> ack miriam<br>
&lt;fantasai> miriam: Not a lot to add, except to say that I agree it's confusing<br>
&lt;fantasai> miriam: I don't know why SASS did it in the first place<br>
&lt;fantasai> miriam: Authors develop convention of putting declarations first<br>
&lt;emilio> q<br>
&lt;fantasai> miriam: but that's not great<br>
&lt;emilio> q+<br>
&lt;fantasai> miriam: we're going to have similar problems with mix-ins in the future<br>
&lt;astearns> ack lea<br>
&lt;fantasai> miriam: be nice to not have a totally different solution<br>
&lt;fantasai> lea: Are we sure it would be a problem with pseudo-elements?<br>
&lt;fantasai> lea: there's no reason to use :is() for a single &amp;<br>
&lt;fantasai> lea: You should just get same selector as parent. If you write something where that substitution isn't fine then you have a problem<br>
&lt;fantasai> lea: [missed]<br>
&lt;fantasai> lea: would enable media queries inside pseudo-elements, which seems important to allow<br>
&lt;astearns> ack emilio<br>
&lt;fantasai> emilio: Using :is() is kinda necessary in the sense that it allows you to avoid expansion, which prevents combnatorial explosion<br>
&lt;astearns> q+<br>
&lt;fantasai> emilio: but maybe special-casing the single &amp; is OK?<br>
&lt;fantasai> emilio: but I suggest we first fix this, at least the bare at-rule issue and then<br>
&lt;lea> s/[missed]/If we don't already do that then we should, even aside from this issue/<br>
&lt;fantasai> emilio: figure out if we need to do this<br>
&lt;fantasai> emilio: It is observable due to specificity, right? This would get the combined specificity of all the items in the selector list<br>
&lt;fantasai> emilio: if you have #foo, bar { .. } then things inside at-rule would be different specificity<br>
&lt;fantasai> emilio: it would be weird to diverge<br>
&lt;fantasai> emilio: it would be weird to make &amp; work differently than in any other position<br>
&lt;fantasai> ntim: :is() will take the higheste specificity<br>
&lt;lea> what emilio is saying is that .foo, #bar { &amp; { color: green } } rn has different specificity than .foo, #bar { color: green } because it's rewritten as :is(.foo, #bar) { color: green }<br>
&lt;fantasai> emilio: which is why it's different. &amp; will get the ID's specificity, even though that matches .foo rather than #bar<br>
&lt;lea> q?<br>
&lt;fantasai> emilio: assuming of course only one of the selectors matches<br>
&lt;fantasai> astearns: One of the arguments against making this change is that people use SASS conventions and nobody puts declarations after nesting anyway<br>
&lt;fantasai> astearns: anecdotally, when I went to search, the 2nd CSS file I looked at had bare declarations after nesting rule for SASS<br>
&lt;fantasai> astearns: probably an accident, but don't think you can say it's not done<br>
&lt;astearns> ack fantasai<br>
&lt;astearns> ack astearns<br>
&lt;emilio> fantasai: couple things emilio brought up and I think are insightful. First is that this is a current problem for @media in pseudo-elements<br>
&lt;lea> +1 to fantasai<br>
&lt;emilio> ... so we need to make it work with nested at rules<br>
&lt;emilio> ... second is that it's weird that that flattening of specificity is very weird and unexpected<br>
&lt;jensimmons> q+<br>
&lt;emilio> ... so I think we should address both of these issues<br>
&lt;emilio> ... but the fact that pseudo-elements are already a concern it means we need to address it<br>
&lt;emilio> ... but it shouldn't block us from solving the cascade<br>
&lt;emilio> ... proposal is that we agree that we're going to fix this<br>
&lt;emilio> ... and try to figure out a right way to fix it<br>
&lt;emilio> ... we could just make that &amp; matches pseudos or something<br>
&lt;emilio> ... or we could come up with another symbol that matches pseudo-elements<br>
&lt;emilio> q+<br>
&lt;astearns> ack jensimmons<br>
&lt;fantasai> jensimmons: Adding to astearns, idea that people will organize their code properly, might have worked out a decade ago when sites were new and got overhauled every few years, and only a few developers<br>
&lt;fantasai> jensimmons: but now teams are much more massive, and code lasts much longer, 5-10 years<br>
&lt;fantasai> jensimmons: and people are scared to reorder styles, touching cascade could break things on other pages<br>
&lt;fantasai> jensimmons: they just jam things in, and might not understand that they're adding things before or after<br>
&lt;astearns> ack emilio<br>
&lt;fantasai> jensimmons: so industry has changed enough that I don't think relying on good CSS organization is workable<br>
&lt;fantasai> emilio: I agree with fantasai that we should bring up those issues and find a coherent way of fixing it<br>
&lt;bradk> +1 to @jensimmons<br>
&lt;lea> q?<br>
&lt;fantasai> emilio: the most striaghtforward solution would be to make &amp; expand to the selector list when it's alone<br>
&lt;lea> q+<br>
&lt;fantasai> emilio: it would solve all the relevant issues here: would make pseudos work, would make @media inside stuff work, and it would make declarations wrapped in &amp; work<br>
&lt;chris> also +1 to @jensimmons this makes css fragile and unmaintainable<br>
&lt;astearns> zakim, close queue<br>
&lt;Zakim> ok, astearns, the speaker queue is closed<br>
&lt;fantasai> emilio: it feels a bit inconsistent, but I think it's the only reasonable solution<br>
&lt;astearns> ack lea<br>
&lt;fantasai> lea: Agree with emilio. even if we decide this isn't the best solution, can invent a better one<br>
&lt;fantasai> lea: but saying that &amp; alone should invoke the selector directly is a good optimization regardles<br>
&lt;fantasai> lea: no reason to have :is() there<br>
&lt;fantasai> lea: good change, solves a bunch of issues, and gives us time to solve the problems down the line<br>
&lt;argyle> i thought :is() only wrapped &amp; when it was a selector list, but that changed somewhere along the line<br>
&lt;jensimmons> +1<br>
&lt;fantasai> lea: and means implementations can update, and that avoids web compat lockdown of waiting<br>
&lt;lea> argyle:<br>
&lt;fantasai> astearns:OK. Let's first resolve that we want to fix this issue, that we want the cascade to use source order<br>
&lt;fantasai> astearns: I haven't heard any arguments against this change, just details<br>
&lt;bradk> +1<br>
&lt;fantasai> RESOLVED: We will address ths issue, and fix nesting to allow for bare declarations after nested rules without moving them above.<br>
&lt;fantasai> astearns: unclear if there's one or two extra issues, can a volunteer untangle?<br>
&lt;fantasai> fantasai: The two issues are, pseudo-elements aren't handled properly by &amp; because it wraps in :is(); and specificity is badly handled because &amp; is wrapped in :is()<br>
&lt;fantasai> lea: should discuss together as one issue<br>
&lt;fantasai> astearns: OK, we're out of time, let's restart this conversation next week<br>
&lt;astearns> s/let's restart this conversation next week//<br>
</details>


-- 
GitHub Notification of comment by css-meeting-bot
Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/8738#issuecomment-1768977689 using your GitHub account


-- 
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config

Received on Wednesday, 18 October 2023 17:04:34 UTC