Skip to content

Commit d643d79

Browse files
authored
Ensure individual logical property utilities are sorted later than left/right pair utilities (#14777)
Resolves #14772. This PR fixes an issue where utilities like `ps-2` were sorted earlier in the generated CSS than `px-3`, causing `ps-2` to not override `px-3` as expected. This happened because `px-3` uses `padding-left` and `padding-right`, and `ps-2` uses `padding-inline-start`, and in `property-order.ts` we sort those properties as follows: ```js ... 'padding', 'padding-inline', 'padding-block', 'padding-inline-start', 'padding-inline-end', 'padding-top', 'padding-right', 'padding-bottom', 'padding-left', ... ``` Since `padding-left` and `padding-right` both appear later than `padding-inline-start`, the `px-3` utility is sorted later in the CSS since all of its properties are later in the sort order than all of properties in `ps-2`. To fix this, I'm using our internal `--tw-sort` property to tell Tailwind to sort the `px-3` utility as if it used `padding-inline` to ensure that it's sorted earlier in the CSS. This PR applies this same fix for the `padding` utilities, `scroll-margin` utilities, and `scroll-padding` utilities. No changes have been made to the `margin` utilities because we were already handling this correctly there. Here you can see that `pl-2` overrides `px-6` as you'd expect: <img width="1041" alt="image" src="https://github.com/user-attachments/assets/fb330536-2131-4de8-a584-62edf380148f"> …and now with the change in this PR, `ps-2` also overrides `px-6` as you'd expect: <img width="1043" alt="image" src="https://github.com/user-attachments/assets/c6799416-9c80-4fd5-bce4-ea1e4da53968"> --------- Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
1 parent 3f2ff03 commit d643d79

File tree

5 files changed

+137
-13
lines changed

5 files changed

+137
-13
lines changed

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10-
- Nothing yet!
10+
### Fixed
11+
12+
- Ensure individual logical property utilities are sorted later than left/right pair utilities ([#14777](https://github.com/tailwindlabs/tailwindcss/pull/14777))
1113

1214
## [4.0.0-alpha.29] - 2024-10-23
1315

packages/tailwindcss/src/index.test.ts

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,100 @@ describe('sorting', () => {
674674
`)
675675
})
676676

677+
it('should sort individual logical properties later than left/right pairs', async () => {
678+
expect(
679+
await compileCss(
680+
css`
681+
@theme {
682+
--spacing-1: 1px;
683+
--spacing-2: 2px;
684+
--spacing-3: 3px;
685+
}
686+
@tailwind utilities;
687+
`,
688+
[
689+
// scroll-margin
690+
'scroll-ms-1',
691+
'scroll-me-2',
692+
'scroll-mx-3',
693+
694+
// scroll-padding
695+
'scroll-ps-1',
696+
'scroll-pe-2',
697+
'scroll-px-3',
698+
699+
// margin
700+
'ms-1',
701+
'me-2',
702+
'mx-3',
703+
704+
// padding
705+
'ps-1',
706+
'pe-2',
707+
'px-3',
708+
].sort(() => Math.random() - 0.5),
709+
),
710+
).toMatchInlineSnapshot(`
711+
":root {
712+
--spacing-1: 1px;
713+
--spacing-2: 2px;
714+
--spacing-3: 3px;
715+
}
716+
717+
.mx-3 {
718+
margin-left: var(--spacing-3, 3px);
719+
margin-right: var(--spacing-3, 3px);
720+
}
721+
722+
.ms-1 {
723+
margin-inline-start: var(--spacing-1, 1px);
724+
}
725+
726+
.me-2 {
727+
margin-inline-end: var(--spacing-2, 2px);
728+
}
729+
730+
.scroll-mx-3 {
731+
scroll-margin-left: var(--spacing-3, 3px);
732+
scroll-margin-right: var(--spacing-3, 3px);
733+
}
734+
735+
.scroll-ms-1 {
736+
scroll-margin-inline-start: var(--spacing-1, 1px);
737+
}
738+
739+
.scroll-me-2 {
740+
scroll-margin-inline-end: var(--spacing-2, 2px);
741+
}
742+
743+
.scroll-px-3 {
744+
scroll-padding-left: var(--spacing-3, 3px);
745+
scroll-padding-right: var(--spacing-3, 3px);
746+
}
747+
748+
.scroll-ps-1 {
749+
scroll-padding-inline-start: var(--spacing-1, 1px);
750+
}
751+
752+
.scroll-pe-2 {
753+
scroll-padding-inline-end: var(--spacing-2, 2px);
754+
}
755+
756+
.px-3 {
757+
padding-left: var(--spacing-3, 3px);
758+
padding-right: var(--spacing-3, 3px);
759+
}
760+
761+
.ps-1 {
762+
padding-inline-start: var(--spacing-1, 1px);
763+
}
764+
765+
.pe-2 {
766+
padding-inline-end: var(--spacing-2, 2px);
767+
}"
768+
`)
769+
})
770+
677771
it('should move variants to the end while sorting', async () => {
678772
expect(
679773
await run(

packages/tailwindcss/src/property-order.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ export default [
9999
'scroll-snap-align',
100100
'scroll-snap-stop',
101101
'scroll-margin',
102+
'scroll-margin-inline',
103+
'scroll-margin-block',
102104
'scroll-margin-inline-start',
103105
'scroll-margin-inline-end',
104106
'scroll-margin-top',
@@ -107,6 +109,8 @@ export default [
107109
'scroll-margin-left',
108110

109111
'scroll-padding',
112+
'scroll-padding-inline',
113+
'scroll-padding-block',
110114
'scroll-padding-inline-start',
111115
'scroll-padding-inline-end',
112116
'scroll-padding-top',

packages/tailwindcss/src/sort.test.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@ function loadDesign() {
1616

1717
const table = [
1818
// Utilities
19-
['px-3 p-1 py-3', 'p-1 py-3 px-3'],
19+
['py-3 p-1 px-3', 'p-1 px-3 py-3'],
2020

2121
// Utilities with variants
22-
['px-3 focus:hover:p-3 hover:p-1 py-3', 'py-3 px-3 hover:p-1 focus:hover:p-3'],
22+
['px-3 focus:hover:p-3 hover:p-1 py-3', 'px-3 py-3 hover:p-1 focus:hover:p-3'],
2323

2424
// Utilities with important
25-
['px-3 py-4! p-1', 'p-1 py-4! px-3'],
26-
['py-4! px-3 p-1', 'p-1 py-4! px-3'],
25+
['px-3 py-4! p-1', 'p-1 px-3 py-4!'],
26+
['py-4! px-3 p-1', 'p-1 px-3 py-4!'],
2727

2828
// User CSS order is the same and moved to the front
2929
['b p-1 a', 'b a p-1'],
@@ -48,11 +48,11 @@ test('can sort classes deterministically across multiple class lists', async ()
4848
let classes = [
4949
[
5050
'a-class px-3 p-1 b-class py-3 bg-red-500 bg-blue-500',
51-
'a-class b-class bg-blue-500 bg-red-500 p-1 py-3 px-3',
51+
'a-class b-class bg-blue-500 bg-red-500 p-1 px-3 py-3',
5252
],
5353
[
5454
'px-3 b-class p-1 py-3 bg-blue-500 a-class bg-red-500',
55-
'b-class a-class bg-blue-500 bg-red-500 p-1 py-3 px-3',
55+
'b-class a-class bg-blue-500 bg-red-500 p-1 px-3 py-3',
5656
],
5757
]
5858

packages/tailwindcss/src/utilities.ts

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1743,13 +1743,21 @@ export function createUtilities(theme: Theme) {
17431743
functionalUtility('scroll-mx', {
17441744
supportsNegative: true,
17451745
themeKeys: ['--scroll-margin', '--spacing'],
1746-
handle: (value) => [decl('scroll-margin-left', value), decl('scroll-margin-right', value)],
1746+
handle: (value) => [
1747+
decl('--tw-sort', 'scroll-margin-inline'),
1748+
decl('scroll-margin-left', value),
1749+
decl('scroll-margin-right', value),
1750+
],
17471751
})
17481752

17491753
functionalUtility('scroll-my', {
17501754
supportsNegative: true,
17511755
themeKeys: ['--scroll-margin', '--spacing'],
1752-
handle: (value) => [decl('scroll-margin-top', value), decl('scroll-margin-bottom', value)],
1756+
handle: (value) => [
1757+
decl('--tw-sort', 'scroll-margin-block'),
1758+
decl('scroll-margin-top', value),
1759+
decl('scroll-margin-bottom', value),
1760+
],
17531761
})
17541762

17551763
functionalUtility('scroll-ms', {
@@ -1798,13 +1806,21 @@ export function createUtilities(theme: Theme) {
17981806
functionalUtility('scroll-px', {
17991807
supportsNegative: true,
18001808
themeKeys: ['--scroll-padding', '--spacing'],
1801-
handle: (value) => [decl('scroll-padding-left', value), decl('scroll-padding-right', value)],
1809+
handle: (value) => [
1810+
decl('--tw-sort', 'scroll-padding-inline'),
1811+
decl('scroll-padding-left', value),
1812+
decl('scroll-padding-right', value),
1813+
],
18021814
})
18031815

18041816
functionalUtility('scroll-py', {
18051817
supportsNegative: true,
18061818
themeKeys: ['--scroll-padding', '--spacing'],
1807-
handle: (value) => [decl('scroll-padding-top', value), decl('scroll-padding-bottom', value)],
1819+
handle: (value) => [
1820+
decl('--tw-sort', 'scroll-padding-block'),
1821+
decl('scroll-padding-top', value),
1822+
decl('scroll-padding-bottom', value),
1823+
],
18081824
})
18091825

18101826
functionalUtility('scroll-ps', {
@@ -2960,12 +2976,20 @@ export function createUtilities(theme: Theme) {
29602976

29612977
functionalUtility('px', {
29622978
themeKeys: ['--padding', '--spacing'],
2963-
handle: (value) => [decl('padding-left', value), decl('padding-right', value)],
2979+
handle: (value) => [
2980+
decl('--tw-sort', 'padding-inline'),
2981+
decl('padding-left', value),
2982+
decl('padding-right', value),
2983+
],
29642984
})
29652985

29662986
functionalUtility('py', {
29672987
themeKeys: ['--padding', '--spacing'],
2968-
handle: (value) => [decl('padding-top', value), decl('padding-bottom', value)],
2988+
handle: (value) => [
2989+
decl('--tw-sort', 'padding-block'),
2990+
decl('padding-top', value),
2991+
decl('padding-bottom', value),
2992+
],
29692993
})
29702994

29712995
functionalUtility('pt', {

0 commit comments

Comments
 (0)