Skip to content

Keep declarations after nested rules inside at-rules - #180

Open
wahidrizka wants to merge 1 commit into
postcss:mainfrom
wahidrizka:fix-at-rule-declaration-order
Open

wahidrizka wants to merge 1 commit into
postcss:mainfrom
wahidrizka:fix-at-rule-declaration-order

Conversation

@wahidrizka

Copy link
Copy Markdown
Contributor

Outside at-rules, declarations after a nested rule keep their place (#92), but inside a bubbled at-rule they are all moved into one rule before the nested rules:

.a { @media (min-width: 1px) { color: red; & { color: blue } color: green } }
/* before: the element is blue */
@media (min-width: 1px) {.a { color: red; color: green } .a { color: blue } }

/* after, like Sass 1.105.1: the element is green */
@media (min-width: 1px) {.a { color: red } .a { color: blue }.a { color: green } }

atruleChilds() collected every declaration of the at-rule into one clone of the parent rule and prepended it. Now it starts a new clone after each nested rule and puts each one where its declarations were, like Rule() does outside at-rules. This covers @media, @supports, @layer, @container and @at-root (without: media). Declarations around a nested at-rule stay together, as in Sass, and unwrapped at-rules like @font-face do not change.

To check it, I compared main (9.0.0) and this branch with Sass on 4,000 distinct generated nested rules. 226 more now match Sass and none stopped matching; the 56 that had the same rules in another order are among them. Of the 293 that still differ, 56 changed: 54 are closer to Sass, and in the other 2 only the known :is(&) selectors differ. In Chrome 154, the output now gives the same color as native nesting for @media, @supports and a :where(.dark) & rule, where main differed in all three. The only changed output without a Sass reference is @at-root without a selector, which Sass rejects when it has declarations; it now keeps their order too.

The new test fails on main. bnt --coverage 100, oxlint and oxfmt --check pass.

Inside a bubbled at-rule, all declarations were moved into one rule
before the nested rules, so `.a { @media x { color: red; & { color:
blue } color: green } }` made the element blue, while Sass and native
CSS nesting keep the order and make it green. Outside at-rules,
declarations after a nested rule already get their own rule (postcss#92), so
do the same inside.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant