Skip to content

Ensure custom variants using @scope generate working CSS#20344

Open
UditDewan wants to merge 2 commits into
tailwindlabs:mainfrom
UditDewan:fix/scope-custom-variant
Open

Ensure custom variants using @scope generate working CSS#20344
UditDewan wants to merge 2 commits into
tailwindlabs:mainfrom
UditDewan:fix/scope-custom-variant

Conversation

@UditDewan

Copy link
Copy Markdown

Summary

Fixes #18961

Custom variants defined with an @scope at-rule currently emit the @scope block nested inside the generated utility class instead of wrapping it:

@custom-variant in-checkout {
  @scope (.checkout) {
    @slot;
  }
}
/* before */
.in-checkout\:underline {
  @scope (.checkout) {
    text-decoration-line: underline;
  }
}

Browsers don't apply @scope in this nested position, so the utility has no effect. Additionally, when the output goes through Lightning CSS the declarations inside the nested @scope are dropped entirely, leaving an empty @scope (.checkout) {} block.

Other conditional at-rules used in custom variants (@media, @supports, @container, @starting-style) are hoisted above the generated style rule when nesting is resolved. This PR adds @scope to the set of hoistable at-rules (and to the droppable-if-empty set, since an empty @scope block has no effect), so the same custom variant now produces:

/* after */
@scope (.checkout) {
  .in-checkout\:underline {
    text-decoration-line: underline;
  }
}

This works with both the block form (@custom-variant name { @scope (…) { @slot; } }) and the shorthand form (@custom-variant name (@scope (…));), and preserves to (…) limits.

Test plan

  • Added tests in index.test.ts covering custom variants using @scope, with and without a to (…) limit (these go through the Lightning CSS optimize step, verifying the output survives minification).
  • Added a test in ast.test.ts verifying @scope is hoisted out of style rules during nesting resolution.
  • vitest run in packages/tailwindcss: 41 test files, 4874 tests passed.

Custom variants defined with an @scope at-rule emitted the @scope block
nested inside the generated utility class instead of wrapping it, so the
resulting CSS had no effect in browsers. Treat @scope like other
conditional at-rules (@media, @supports, @container) when resolving
nesting, so it is hoisted above the generated style rules.

Fixes tailwindlabs#18961
@UditDewan
UditDewan requested a review from a team as a code owner July 16, 2026 22:36
@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Caution

Review failed

An error occurred during the review process. Please try again later.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Confidence Score: 5/5

Safe to merge — the change is a two-line addition to two well-understood constant sets, and the tests cover the key block-form paths end-to-end through Lightning CSS.

The fix is minimal and targeted: @scope is added to the same two constant sets that govern how @media, @supports, and @container are handled. The hoisting algorithm already works correctly for all those cases; @scope has the same structural requirements. Tests confirm both the AST-level hoisting and the full Tailwind compilation path, with and without a to (…) limit.

No files require special attention. The only substantive code change is in ast.ts, and its behavior is validated by the new tests in ast.test.ts and index.test.ts.

Reviews (1): Last reviewed commit: "Add changelog entry" | Re-trigger Greptile

@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

An error occurred during the review process. Please try again later.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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.

Custom variants don't work with @scope

1 participant