Skip to content

postcss-nesting: nested conditionals #1368

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

Merged
merged 3 commits into from
Apr 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions plugins/postcss-nesting/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,28 @@
# Changes to PostCSS Nesting

### Unreleased (patch)

- Edition `2024-02`:
- Do not rewrite selectors for declarations in conditional rules to a form with `:is()`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this indent intentional?

Also, I assume you want to patch this after the major?

Copy link
Member Author

@romainmenke romainmenke Apr 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before the major.

This is a minimally breaking change.
(Any change theoretically is a breaking change for someone.)

It is only breaking when having something like this :

a, .link {
  @media (min-width: 64rem) {
    color: blue;
  }
}

a {
  color: red;
}

Before this change blue would have specificity [0, 1, 0] because of :is() and would overrule red.

After this change blue will have specificity [0, 0, 1] and red will have win because it appears later.

So it only affects declarations in nested conditionals that became more specific as a result of :is() and had lower specificity declarations appearing after it.

User that do depend on the :is() behavior would need to opt-in by writing :

a, .link {
  @media (min-width: 64rem) {
    & {
      color: blue;
    }
  }
}

a {
  color: red;
}

Chrome had a use counter for this and other patterns that would be affected by this change as the result was extremely low:

CSSNestedGroupRuleSpecificity (0.00017%), which triggers when @nest-wrapping bare declarations within a nested group rule would make a difference to the cascade. Making this move would allow nesting e.g. @media in pseudo-element rules, which doesn't work currently since we're wrapping in an &-rule.

I am sure that our users will have a higher number (Chrome doesn't see what we transpile away) but hoping that the pattern is still sufficiently rare.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh, makes sense!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this indent intentional?

Forgot to address this

This change is specific to that edition.
It doesn't affect the plugin as a whole.

That indent will make it a nested (no pun intended) list item.


This will work:
```css
::before, ::after {
color: blue;

@media screen { color: cyan; }
}
```

This still **wont** work:
```css
::before, ::after {
color: blue;

&:hover { color: cyan; }
}
```

### 12.1.1

_March 31, 2024_
Expand Down
2 changes: 1 addition & 1 deletion plugins/postcss-nesting/dist/index.cjs

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion plugins/postcss-nesting/dist/index.mjs

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import type { AtRule, Result, Rule } from 'postcss';
import type { walkFunc } from './walk-func.js';
import cleanupParent from '../../shared/lib/cleanup-parent.js';
import mergeSelectors from './merge-selectors.js';
import shiftNodesBeforeParent from '../../shared/lib/shift-nodes-before-parent.js';
import validAtrules from '../../shared/lib/valid-atrules.js';

Expand All @@ -13,13 +12,6 @@ export default function atruleWithinRule(node: AtRule, parent: Rule, result: Res
if (node.nodes) {
const rule = parent.clone().removeAll().append(node.nodes);

const selectors = mergeSelectors(node, '&', parent.selector, result);
if (!selectors) {
return;
}

rule.selector = selectors;

// append the new rule to the node
node.append(rule);

Expand Down
8 changes: 4 additions & 4 deletions plugins/postcss-nesting/test/media.edition-2024-02.expect.css
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ a {
}
}
@media (max-width: 200px) {
:is(a b) {
a b {
order: 4;
}
}
Expand Down Expand Up @@ -39,7 +39,7 @@ a {
}
}
@media (max-width: 200px) {
:is(a b) {
a b {
order: 4;
}
}
Expand All @@ -57,14 +57,14 @@ a {

@media screen {

:is(a,.a) {
a, .a {
order: 7;
}
}

@media screen {

:is(a,a::after) {
a, a::after {
order: 8;
}
}
Expand Down
24 changes: 16 additions & 8 deletions plugins/postcss-nesting/test/spec-examples.css
Original file line number Diff line number Diff line change
Expand Up @@ -377,10 +377,6 @@ article {
color: blue;
}

/*
NOTE : We are more forgiving than the spec
This declaration is preserved
*/
color: red;
}

Expand All @@ -391,10 +387,6 @@ article {
color: blue;
}

/*
NOTE : We are more forgiving than the spec
This declaration is preserved
*/
color: red;

&.foo {
Expand All @@ -403,3 +395,19 @@ article {

/* valid! */
}

::after, .foo {
color: green;

& {
color: blue;
}

color: red;

@media screen {
color: purple;
}

color: orange;
}
Original file line number Diff line number Diff line change
Expand Up @@ -353,10 +353,6 @@ article {
article {
color: blue;

/*
NOTE : We are more forgiving than the spec
This declaration is preserved
*/
color: red;
}

Expand All @@ -367,10 +363,6 @@ article {
article {
color: blue;

/*
NOTE : We are more forgiving than the spec
This declaration is preserved
*/
color: red;
}

Expand All @@ -379,3 +371,28 @@ article.foo {
}

/* valid! */

::after, .foo {
color: green;
}

:is(::after,.foo) {
color: blue;
}

::after, .foo {

color: red;
}

@media screen {

::after, .foo {
color: purple;
}
}

::after, .foo {

color: orange;
}
27 changes: 19 additions & 8 deletions plugins/postcss-nesting/test/spec-examples.expect.css
Original file line number Diff line number Diff line change
Expand Up @@ -358,10 +358,6 @@ __bar.foo {
article {
color: green;

/*
NOTE : We are more forgiving than the spec
This declaration is preserved
*/
color: red;
}
article {
Expand All @@ -371,10 +367,6 @@ article {
article {
color: green;

/*
NOTE : We are more forgiving than the spec
This declaration is preserved
*/
color: red;
}

Expand All @@ -387,3 +379,22 @@ article.foo {
}

/* valid! */

::after, .foo {
color: green;

color: red;

color: orange;
}

:is(::after,.foo) {
color: blue;
}

@media screen {

::after, .foo {
color: purple;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -358,10 +358,6 @@ __bar.foo {
article {
color: green;

/*
NOTE : We are more forgiving than the spec
This declaration is preserved
*/
color: red;
}
article {
Expand All @@ -371,10 +367,6 @@ article {
article {
color: green;

/*
NOTE : We are more forgiving than the spec
This declaration is preserved
*/
color: red;
}

Expand All @@ -387,3 +379,22 @@ article.foo {
}

/* valid! */

::after, .foo {
color: green;

color: red;

color: orange;
}

::after, .foo {
color: blue;
}

@media screen {

::after, .foo {
color: purple;
}
}