diff --git a/CHANGELOG.md b/CHANGELOG.md index a7ba50dcd..cb433421f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Export missing `PluginWithConfig` type from `tailwindcss/plugin` to fix errors when inferring plugin config types ([#19707](https://github.com/tailwindlabs/tailwindcss/pull/19707)) - Ensure `start` and `end` legacy utilities without values do not generate CSS ([#20003](https://github.com/tailwindlabs/tailwindcss/pull/20003)) - Ensure `--value(…)` is required in functional `@utility` definitions ([#20005](https://github.com/tailwindlabs/tailwindcss/pull/20005)) +- Canonicalization: preserve required whitespace around operators in negated arbitrary values (e.g. `-left-[(var(--a)+var(--b))]`) ([#20011](https://github.com/tailwindlabs/tailwindcss/pull/20011)) ## [4.2.4] - 2026-04-21 diff --git a/packages/tailwindcss/src/utilities.test.ts b/packages/tailwindcss/src/utilities.test.ts index 219302ae3..6b018f672 100644 --- a/packages/tailwindcss/src/utilities.test.ts +++ b/packages/tailwindcss/src/utilities.test.ts @@ -1109,6 +1109,9 @@ test('left', async () => { 'left-4', '-left-4', 'left-[4px]', + + // https://github.com/tailwindlabs/tailwindcss/issues/20010 + '-left-[(var(--my-var1)+var(--my-var2))]', ], ), ).toMatchInlineSnapshot(` @@ -1121,6 +1124,10 @@ test('left', async () => { left: calc(var(--spacing-4) * -1); } + .-left-\\[\\(var\\(--my-var1\\)\\+var\\(--my-var2\\)\\)\\] { + left: calc((var(--my-var1) + var(--my-var2)) * -1); + } + .-left-full { left: -100%; } diff --git a/packages/tailwindcss/src/utilities.ts b/packages/tailwindcss/src/utilities.ts index 565b64523..c40f3be93 100644 --- a/packages/tailwindcss/src/utilities.ts +++ b/packages/tailwindcss/src/utilities.ts @@ -24,6 +24,7 @@ import { isValidOpacityValue, isValidSpacingMultiplier, } from './utils/infer-data-type' +import { addWhitespaceAroundMathOperators } from './utils/math-operators' import { replaceShadowColors } from './utils/replace-shadow-colors' import { segment } from './utils/segment' import * as ValueParser from './value-parser' @@ -450,7 +451,10 @@ export function createUtilities(theme: Theme) { if (value === null) return // Negate the value if the candidate has a negative prefix. - return desc.handle(negative ? `calc(${value} * -1)` : value, dataType) + return desc.handle( + negative ? addWhitespaceAroundMathOperators(`calc(${value} * -1)`) : value, + dataType, + ) } }