Skip to content

Commit ebfde31

Browse files
authored
Add safe alignment utilities (#14607)
Fixes #7929 and #12916 This PR adds [safe alignment utilities](https://www.stefanjudis.com/today-i-learned/safe-unsafe-alignment-in-css-flexbox/) to Tailwind 4. I opted to include them for every justify/align content/items/self property, but only for the `end` and `center` values. I know that it doesn't make sense for `start` (as the point of safe alignment is to fall back to `start` when it overflows), but I'm not sure about `space-between`, `space-around`, or other values. I certainly never encountered a situation where I needed `safe` with those.
1 parent 1d2d50e commit ebfde31

File tree

5 files changed

+147
-1
lines changed

5 files changed

+147
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1515
- _Experimental_: Add `items-baseline-last` utility ([#12128](https://github.com/tailwindlabs/tailwindcss/pull/12128))
1616
- _Experimental_: Add `pointer-none`, `pointer-coarse`, and `pointer-fine` variant ([#16946](https://github.com/tailwindlabs/tailwindcss/pull/16946))
1717
- _Experimental_: Add `any-pointer-none`, `any-pointer-coarse`, and `any-pointer-fine` variants ([#16941](https://github.com/tailwindlabs/tailwindcss/pull/16941))
18+
- _Experimental_: Add safe alignment utilities ([#14607](https://github.com/tailwindlabs/tailwindcss/pull/14607))
1819
- _Experimental_: Add `user-valid` and `user-invalid` variants ([#12370](https://github.com/tailwindlabs/tailwindcss/pull/12370))
1920
- _Experimental_: Add `wrap-anywhere`, `wrap-break-word`, and `wrap-normal` utilities ([#12128](https://github.com/tailwindlabs/tailwindcss/pull/12128))
2021
- _Experimental_: Add `@source inline(…)` ([#17147](https://github.com/tailwindlabs/tailwindcss/pull/17147))

packages/tailwindcss/src/__snapshots__/intellisense.test.ts.snap

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3746,7 +3746,9 @@ exports[`getClassList 1`] = `
37463746
"content-baseline",
37473747
"content-between",
37483748
"content-center",
3749+
"content-center-safe",
37493750
"content-end",
3751+
"content-end-safe",
37503752
"content-evenly",
37513753
"content-none",
37523754
"content-normal",
@@ -4877,24 +4879,32 @@ exports[`getClassList 1`] = `
48774879
"items-baseline",
48784880
"items-baseline-last",
48794881
"items-center",
4882+
"items-center-safe",
48804883
"items-end",
4884+
"items-end-safe",
48814885
"items-start",
48824886
"items-stretch",
48834887
"justify-around",
48844888
"justify-baseline",
48854889
"justify-between",
48864890
"justify-center",
4891+
"justify-center-safe",
48874892
"justify-end",
4893+
"justify-end-safe",
48884894
"justify-evenly",
48894895
"justify-items-center",
4896+
"justify-items-center-safe",
48904897
"justify-items-end",
4898+
"justify-items-end-safe",
48914899
"justify-items-normal",
48924900
"justify-items-start",
48934901
"justify-items-stretch",
48944902
"justify-normal",
48954903
"justify-self-auto",
48964904
"justify-self-center",
4905+
"justify-self-center-safe",
48974906
"justify-self-end",
4907+
"justify-self-end-safe",
48984908
"justify-self-start",
48994909
"justify-self-stretch",
49004910
"justify-start",
@@ -6005,18 +6015,24 @@ exports[`getClassList 1`] = `
60056015
"place-content-baseline",
60066016
"place-content-between",
60076017
"place-content-center",
6018+
"place-content-center-safe",
60086019
"place-content-end",
6020+
"place-content-end-safe",
60096021
"place-content-evenly",
60106022
"place-content-start",
60116023
"place-content-stretch",
60126024
"place-items-baseline",
60136025
"place-items-center",
6026+
"place-items-center-safe",
60146027
"place-items-end",
6028+
"place-items-end-safe",
60156029
"place-items-start",
60166030
"place-items-stretch",
60176031
"place-self-auto",
60186032
"place-self-center",
6033+
"place-self-center-safe",
60196034
"place-self-end",
6035+
"place-self-end-safe",
60206036
"place-self-start",
60216037
"place-self-stretch",
60226038
"placeholder-current",
@@ -7280,7 +7296,9 @@ exports[`getClassList 1`] = `
72807296
"self-auto",
72817297
"self-baseline",
72827298
"self-center",
7299+
"self-center-safe",
72837300
"self-end",
7301+
"self-end-safe",
72847302
"self-start",
72857303
"self-stretch",
72867304
"sepia",

packages/tailwindcss/src/feature-flags.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ export const enableBaselineLast = process.env.FEATURES_ENV !== 'stable'
22
export const enableDetailsContent = process.env.FEATURES_ENV !== 'stable'
33
export const enableInvertedColors = process.env.FEATURES_ENV !== 'stable'
44
export const enablePointerVariants = process.env.FEATURES_ENV !== 'stable'
5+
export const enableSafeAlignment = process.env.FEATURES_ENV !== 'stable'
56
export const enableScripting = process.env.FEATURES_ENV !== 'stable'
67
export const enableSourceInline = process.env.FEATURES_ENV !== 'stable'
78
export const enableUserValid = process.env.FEATURES_ENV !== 'stable'

packages/tailwindcss/src/utilities.test.ts

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7125,8 +7125,10 @@ test('place-content', async () => {
71257125
expect(
71267126
await run([
71277127
'place-content-center',
7128+
'place-content-center-safe',
71287129
'place-content-start',
71297130
'place-content-end',
7131+
'place-content-end-safe',
71307132
'place-content-between',
71317133
'place-content-around',
71327134
'place-content-evenly',
@@ -7150,10 +7152,18 @@ test('place-content', async () => {
71507152
place-content: center;
71517153
}
71527154
7155+
.place-content-center-safe {
7156+
place-content: safe center;
7157+
}
7158+
71537159
.place-content-end {
71547160
place-content: end;
71557161
}
71567162
7163+
.place-content-end-safe {
7164+
place-content: safe end;
7165+
}
7166+
71577167
.place-content-evenly {
71587168
place-content: space-evenly;
71597169
}
@@ -7194,7 +7204,9 @@ test('place-items', async () => {
71947204
await run([
71957205
'place-items-start',
71967206
'place-items-end',
7207+
'place-items-end-safe',
71977208
'place-items-center',
7209+
'place-items-center-safe',
71987210
'place-items-baseline',
71997211
'place-items-stretch',
72007212
]),
@@ -7207,10 +7219,18 @@ test('place-items', async () => {
72077219
place-items: center;
72087220
}
72097221
7222+
.place-items-center-safe {
7223+
place-items: safe center;
7224+
}
7225+
72107226
.place-items-end {
72117227
place-items: end;
72127228
}
72137229
7230+
.place-items-end-safe {
7231+
place-items: safe end;
7232+
}
7233+
72147234
.place-items-start {
72157235
place-items: start;
72167236
}
@@ -7241,8 +7261,10 @@ test('align-content', async () => {
72417261
await run([
72427262
'content-normal',
72437263
'content-center',
7264+
'content-center-safe',
72447265
'content-start',
72457266
'content-end',
7267+
'content-end-safe',
72467268
'content-between',
72477269
'content-around',
72487270
'content-evenly',
@@ -7266,10 +7288,18 @@ test('align-content', async () => {
72667288
align-content: center;
72677289
}
72687290
7291+
.content-center-safe {
7292+
align-content: safe center;
7293+
}
7294+
72697295
.content-end {
72707296
align-content: flex-end;
72717297
}
72727298
7299+
.content-end-safe {
7300+
align-content: safe flex-end;
7301+
}
7302+
72737303
.content-evenly {
72747304
align-content: space-evenly;
72757305
}
@@ -7316,7 +7346,9 @@ test('items', async () => {
73167346
await run([
73177347
'items-start',
73187348
'items-end',
7349+
'items-end-safe',
73197350
'items-center',
7351+
'items-center-safe',
73207352
'items-baseline',
73217353
'items-baseline-last',
73227354
'items-stretch',
@@ -7334,10 +7366,18 @@ test('items', async () => {
73347366
align-items: center;
73357367
}
73367368
7369+
.items-center-safe {
7370+
align-items: safe center;
7371+
}
7372+
73377373
.items-end {
73387374
align-items: flex-end;
73397375
}
73407376
7377+
.items-end-safe {
7378+
align-items: safe flex-end;
7379+
}
7380+
73417381
.items-start {
73427382
align-items: flex-start;
73437383
}
@@ -7371,7 +7411,9 @@ test('justify', async () => {
73717411
'justify-normal',
73727412
'justify-start',
73737413
'justify-end',
7414+
'justify-end-safe',
73747415
'justify-center',
7416+
'justify-center-safe',
73757417
'justify-between',
73767418
'justify-around',
73777419
'justify-evenly',
@@ -7390,10 +7432,18 @@ test('justify', async () => {
73907432
justify-content: center;
73917433
}
73927434
7435+
.justify-center-safe {
7436+
justify-content: safe center;
7437+
}
7438+
73937439
.justify-end {
73947440
justify-content: flex-end;
73957441
}
73967442
7443+
.justify-end-safe {
7444+
justify-content: safe flex-end;
7445+
}
7446+
73977447
.justify-evenly {
73987448
justify-content: space-evenly;
73997449
}
@@ -7438,18 +7488,28 @@ test('justify-items', async () => {
74387488
await run([
74397489
'justify-items-start',
74407490
'justify-items-end',
7491+
'justify-items-end-safe',
74417492
'justify-items-center',
7493+
'justify-items-center-safe',
74427494
'justify-items-stretch',
74437495
]),
74447496
).toMatchInlineSnapshot(`
74457497
".justify-items-center {
74467498
justify-items: center;
74477499
}
74487500
7501+
.justify-items-center-safe {
7502+
justify-items: safe center;
7503+
}
7504+
74497505
.justify-items-end {
74507506
justify-items: end;
74517507
}
74527508
7509+
.justify-items-end-safe {
7510+
justify-items: safe end;
7511+
}
7512+
74537513
.justify-items-start {
74547514
justify-items: start;
74557515
}
@@ -8298,7 +8358,9 @@ test('place-self', async () => {
82988358
'place-self-auto',
82998359
'place-self-start',
83008360
'place-self-end',
8361+
'place-self-end-safe',
83018362
'place-self-center',
8363+
'place-self-center-safe',
83028364
'place-self-stretch',
83038365
]),
83048366
).toMatchInlineSnapshot(`
@@ -8310,10 +8372,18 @@ test('place-self', async () => {
83108372
place-self: center;
83118373
}
83128374
8375+
.place-self-center-safe {
8376+
place-self: safe center;
8377+
}
8378+
83138379
.place-self-end {
83148380
place-self: end;
83158381
}
83168382
8383+
.place-self-end-safe {
8384+
place-self: safe end;
8385+
}
8386+
83178387
.place-self-start {
83188388
place-self: start;
83198389
}
@@ -8345,7 +8415,9 @@ test('self', async () => {
83458415
'self-auto',
83468416
'self-start',
83478417
'self-end',
8418+
'self-end-safe',
83488419
'self-center',
8420+
'self-center-safe',
83498421
'self-stretch',
83508422
'self-baseline',
83518423
]),
@@ -8362,10 +8434,18 @@ test('self', async () => {
83628434
align-self: center;
83638435
}
83648436
8437+
.self-center-safe {
8438+
align-self: safe center;
8439+
}
8440+
83658441
.self-end {
83668442
align-self: flex-end;
83678443
}
83688444
8445+
.self-end-safe {
8446+
align-self: safe flex-end;
8447+
}
8448+
83698449
.self-start {
83708450
align-self: flex-start;
83718451
}
@@ -8399,7 +8479,9 @@ test('justify-self', async () => {
83998479
'justify-self-auto',
84008480
'justify-self-start',
84018481
'justify-self-end',
8482+
'justify-self-end-safe',
84028483
'justify-self-center',
8484+
'justify-self-center-safe',
84038485
'justify-self-stretch',
84048486
'justify-self-baseline',
84058487
]),
@@ -8412,10 +8494,18 @@ test('justify-self', async () => {
84128494
justify-self: center;
84138495
}
84148496
8497+
.justify-self-center-safe {
8498+
justify-self: safe center;
8499+
}
8500+
84158501
.justify-self-end {
84168502
justify-self: flex-end;
84178503
}
84188504
8505+
.justify-self-end-safe {
8506+
justify-self: safe flex-end;
8507+
}
8508+
84198509
.justify-self-start {
84208510
justify-self: flex-start;
84218511
}

0 commit comments

Comments
 (0)