Skip to content

Commit

Permalink
Prevent not-* from being used with variants with multiple sibling r…
Browse files Browse the repository at this point in the history
…ules (#15689)

Variants like this can't be easily negated by our current system:

```css
@custom-variant dark {
  &.is-dark {
    @slot;
  }
  @media (prefers-color-scheme: dark) {
    @slot;
  }
}
```

Right now it produces the following CSS which is logically incorrect:

```css
.utility-name {
  &:not(.is-dark) {
    /* ... */
  }

  @media not (prefers-color-scheme: dark) {
    /* ... */
  }
}
```

The correct CSS is this which requires moving things around:
```css
.utility-name {
  @media not (prefers-color-scheme: dark) {
    &:not(.is-dark) {
      /* ... */
    }
  }
}
```

We're opting to disable this instead of generating incorrect CSS for
now. I'd like to bring this back in the future for simpler cases in the
future.
  • Loading branch information
thecrypticace authored Jan 21, 2025
1 parent 4035ab0 commit 79f21a8
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 11 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Ensure `-outline-offset-*` utilities are suggested in IntelliSense ([#15646](https://github.com/tailwindlabs/tailwindcss/pull/15646))
- Write to `stdout` when `--output` is set to `-` or omitted for `@tailwindcss/cli` ([#15656](https://github.com/tailwindlabs/tailwindcss/pull/15656))
- Write to `stdout` when `--output -` flag is used for `@tailwindcss/cli` ([#15656](https://github.com/tailwindlabs/tailwindcss/pull/15656))
- Prevent `not-*` from being used with variants that have multiple sibling rules ([#15689](https://github.com/tailwindlabs/tailwindcss/pull/15689))
- _Upgrade (experimental)_: Pretty print `--spacing(…)` to prevent ambiguity ([#15596](https://github.com/tailwindlabs/tailwindcss/pull/15596))

### Changed
Expand Down
9 changes: 9 additions & 0 deletions packages/tailwindcss/src/compile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,15 @@ export function applyVariant(
let result = applyVariant(isolatedNode, variant.variant, variants, depth + 1)
if (result === null) return null

if (variant.root === 'not' && isolatedNode.nodes.length > 1) {
// The `not` variant cannot negate sibling rules / at-rules because these
// are an OR relationship. Doing so would require transforming sibling
// nodes into nesting while negating them. This isn't possible with the
// current implementation of the `not` variant or with how variants are
// applied in general (on a per-node basis).
return null
}

for (let child of isolatedNode.nodes) {
// Only some variants wrap children in rules. For example, the `force`
// variant is a noop on the AST. And the `has` variant modifies the
Expand Down
50 changes: 39 additions & 11 deletions packages/tailwindcss/src/variants.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1644,6 +1644,30 @@ test('not', async () => {
}
}
}
@custom-variant parallel-style-rules {
&:hover {
@slot;
}
&:focus {
@slot;
}
}
@custom-variant parallel-at-rules {
@media foo {
@slot;
}
@media bar {
@slot;
}
}
@custom-variant parallel-mixed-rules {
&:hover {
@slot;
}
@media bar {
@slot;
}
}
@tailwind utilities;
`,
[
Expand All @@ -1660,23 +1684,27 @@ test('not', async () => {
'not-multiple-media-conditions:flex',
'not-starting:flex',

'not-parallel-style-rules:flex',
'not-parallel-at-rules:flex',
'not-parallel-mixed-rules:flex',

// The following built-in variants don't have not-* versions because
// there is no sensible negative version of them.

// These just don't make sense as not-*
'not-force',
'not-*',
'not-force:flex',
'not-*:flex',

// These contain pseudo-elements
'not-first-letter',
'not-first-line',
'not-marker',
'not-selection',
'not-file',
'not-placeholder',
'not-backdrop',
'not-before',
'not-after',
'not-first-letter:flex',
'not-first-line:flex',
'not-marker:flex',
'not-selection:flex',
'not-file:flex',
'not-placeholder:flex',
'not-backdrop:flex',
'not-before:flex',
'not-after:flex',

// This is not a conditional at rule
'not-starting:flex',
Expand Down

0 comments on commit 79f21a8

Please sign in to comment.