Skip to content

Commit f302fce

Browse files
authored
Fix canonicalization resulting in empty list (#19812)
This PR fixes a bug in the canonicalization process where if a few utilities collapse into a smaller one, and the smaller one is part of the original list, then it results in an empty list. It will be more clear with an example. Let's say you have this setup: ``` w-[calc(1rem+0.25rem)] h-[calc(1rem+0.25rem)] size-5 ``` The first step is that this will result in: ``` w-5 h-5 size-5 ``` Then the `w-5 h-5` can turn into `size-5`. But the existing `size-5`, can also be replaced by the `size-5`. Internally, when we have a replacement, then we mark all the classes that can be replaced as "droppable", so they would be dropped from the list. But in this scenario we also marked `size-5` as droppable, resulting in an empty list. If an additional class existed: ``` w-[calc(1rem+0.25rem)] h-[calc(1rem+0.25rem)] size-5 flex ``` The result would be ``` flex ``` Instead of the expected: ``` size-5 flex ``` ## Test plan 1. Existing tests pass 2. Added new tests with and without an additional class
1 parent bb2f170 commit f302fce

File tree

3 files changed

+19
-4
lines changed

3 files changed

+19
-4
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1919
- Skip full reload for server only modules scanned by client CSS when using `@tailwindcss/vite` ([#19745](https://github.com/tailwindlabs/tailwindcss/pull/19745))
2020
- Add support for Vite 8 in `@tailwindcss/vite` ([#19790](https://github.com/tailwindlabs/tailwindcss/pull/19790))
2121
- Improve canonicalization for bare values exceeding default spacing scale suggestions (e.g. `w-1234 h-1234``size-1234`) ([#19809](https://github.com/tailwindlabs/tailwindcss/pull/19809))
22+
- Fix canonicalization resulting in empty list (e.g. `w-5 h-5 size-5` → `` instead of `size-5`) ([#19812](https://github.com/tailwindlabs/tailwindcss/pull/19812))
2223

2324
## [4.2.1] - 2026-02-23
2425

packages/tailwindcss/src/canonicalize-candidates.test.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1061,6 +1061,16 @@ describe.each([['default'], ['with-variant'], ['important'], ['prefix']])('%s',
10611061
['w-128 h-128', 'size-128'], // `w-128` on its own would become `w-lg`
10621062
['mt-123 mb-123', 'my-123'],
10631063

1064+
// Collapse duplicates into themselves
1065+
['w-8 w-8', 'w-8'],
1066+
1067+
// `w-*` and `h-*` would canonicalize to `size-5`
1068+
// `size-5` and `size-5` should then canonicalize to `size-5`
1069+
['w-[calc(1rem+0.25rem)] h-[calc(1rem+0.25rem)] size-5', 'size-5'],
1070+
1071+
// Same as above, but with an additional unrelated class
1072+
['w-[calc(1rem+0.25rem)] h-[calc(1rem+0.25rem)] size-5 flex', 'size-5 flex'],
1073+
10641074
// Do not touch if not operating on the same variants
10651075
['hover:w-4 h-4', 'hover:w-4 h-4'],
10661076

packages/tailwindcss/src/canonicalize-candidates.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -446,13 +446,17 @@ function collapseCandidates(options: InternalCanonicalizeOptions, candidates: st
446446
designSystem.storage[UTILITY_SIGNATURE_KEY].get(signatureOptions).get(replacement)
447447
if (signature !== collapsedSignature) continue // Not a safe replacement
448448

449-
// We can replace all items in the combo with the replacement
449+
// Use the replacement
450+
result.add(replacement)
451+
452+
// We can replace all items in the combo with the replacement. If the
453+
// replacement is already part of the combo, keep that one around.
450454
for (let item of combo) {
451-
drop.add(candidates[item])
455+
if (candidates[item] !== replacement) {
456+
drop.add(candidates[item])
457+
}
452458
}
453459

454-
// Use the replacement
455-
result.add(replacement)
456460
break
457461
}
458462
}

0 commit comments

Comments
 (0)