Skip to content

Commit 1aa6fb4

Browse files
Use @layer properties for @property polyfills
1 parent 6a0a3ec commit 1aa6fb4

File tree

11 files changed

+288
-273
lines changed

11 files changed

+288
-273
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+
- Don't rely on `@layer base` for the `@property` polyfills ([#17506](https://github.com/tailwindlabs/tailwindcss/pull/17506))
1113

1214
## [4.1.1] - 2025-04-02
1315

integrations/cli/index.test.ts

Lines changed: 45 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -713,13 +713,7 @@ test(
713713
expect(await fs.dumpFiles('./dist/*.css')).toMatchInlineSnapshot(`
714714
"
715715
--- ./dist/out.css ---
716-
@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
717-
@layer base {
718-
*, ::before, ::after, ::backdrop {
719-
--tw-content: "";
720-
}
721-
}
722-
}
716+
@layer properties;
723717
.content-\\[\\"components\\/my-component\\.tsx\\"\\] {
724718
--tw-content: "components/my-component.tsx";
725719
content: var(--tw-content);
@@ -761,6 +755,13 @@ test(
761755
inherits: false;
762756
initial-value: "";
763757
}
758+
@layer properties {
759+
@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
760+
*, ::before, ::after, ::backdrop {
761+
--tw-content: "";
762+
}
763+
}
764+
}
764765
"
765766
`)
766767
},
@@ -951,13 +952,7 @@ test(
951952
expect(await fs.dumpFiles('./project-a/dist/*.css')).toMatchInlineSnapshot(`
952953
"
953954
--- ./project-a/dist/out.css ---
954-
@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
955-
@layer base {
956-
*, ::before, ::after, ::backdrop {
957-
--tw-content: "";
958-
}
959-
}
960-
}
955+
@layer properties;
961956
.content-\\[\\'project-a\\/node_modules\\/my-lib-1\\/src\\/index\\.html\\'\\] {
962957
--tw-content: 'project-a/node modules/my-lib-1/src/index.html';
963958
content: var(--tw-content);
@@ -1011,6 +1006,13 @@ test(
10111006
inherits: false;
10121007
initial-value: "";
10131008
}
1009+
@layer properties {
1010+
@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
1011+
*, ::before, ::after, ::backdrop {
1012+
--tw-content: "";
1013+
}
1014+
}
1015+
}
10141016
"
10151017
`)
10161018

@@ -1195,13 +1197,7 @@ test(
11951197
expect(await fs.dumpFiles('./dist/*.css')).toMatchInlineSnapshot(`
11961198
"
11971199
--- ./dist/out.css ---
1198-
@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
1199-
@layer base {
1200-
*, ::before, ::after, ::backdrop {
1201-
--tw-content: "";
1202-
}
1203-
}
1204-
}
1200+
@layer properties;
12051201
.content-\\[\\"pages\\/foo\\.html\\"\\] {
12061202
--tw-content: "pages/foo.html";
12071203
content: var(--tw-content);
@@ -1219,6 +1215,13 @@ test(
12191215
inherits: false;
12201216
initial-value: "";
12211217
}
1218+
@layer properties {
1219+
@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
1220+
*, ::before, ::after, ::backdrop {
1221+
--tw-content: "";
1222+
}
1223+
}
1224+
}
12221225
"
12231226
`)
12241227
},
@@ -1588,27 +1591,8 @@ test(
15881591
"
15891592
--- ./dist/out.css ---
15901593
@import url('https://fonts.googleapis.com');
1594+
@layer properties;
15911595
@layer theme, base, components, utilities;
1592-
@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
1593-
@layer base {
1594-
*, ::before, ::after, ::backdrop {
1595-
--tw-shadow: 0 0 #0000;
1596-
--tw-shadow-color: initial;
1597-
--tw-shadow-alpha: 100%;
1598-
--tw-inset-shadow: 0 0 #0000;
1599-
--tw-inset-shadow-color: initial;
1600-
--tw-inset-shadow-alpha: 100%;
1601-
--tw-ring-color: initial;
1602-
--tw-ring-shadow: 0 0 #0000;
1603-
--tw-inset-ring-color: initial;
1604-
--tw-inset-ring-shadow: 0 0 #0000;
1605-
--tw-ring-inset: initial;
1606-
--tw-ring-offset-width: 0px;
1607-
--tw-ring-offset-color: #fff;
1608-
--tw-ring-offset-shadow: 0 0 #0000;
1609-
}
1610-
}
1611-
}
16121596
@layer theme {
16131597
:root, :host {
16141598
--font-sans: ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol',
@@ -1839,6 +1823,26 @@ test(
18391823
inherits: false;
18401824
initial-value: 0 0 #0000;
18411825
}
1826+
@layer properties {
1827+
@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
1828+
*, ::before, ::after, ::backdrop {
1829+
--tw-shadow: 0 0 #0000;
1830+
--tw-shadow-color: initial;
1831+
--tw-shadow-alpha: 100%;
1832+
--tw-inset-shadow: 0 0 #0000;
1833+
--tw-inset-shadow-color: initial;
1834+
--tw-inset-shadow-alpha: 100%;
1835+
--tw-ring-color: initial;
1836+
--tw-ring-shadow: 0 0 #0000;
1837+
--tw-inset-ring-color: initial;
1838+
--tw-inset-ring-shadow: 0 0 #0000;
1839+
--tw-ring-inset: initial;
1840+
--tw-ring-offset-width: 0px;
1841+
--tw-ring-offset-color: #fff;
1842+
--tw-ring-offset-shadow: 0 0 #0000;
1843+
}
1844+
}
1845+
}
18421846
"
18431847
`)
18441848
},

packages/@tailwindcss-postcss/src/__snapshots__/index.test.ts.snap

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
11
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
22

33
exports[`\`@import 'tailwindcss'\` is replaced with the generated CSS 1`] = `
4-
"@layer theme {
4+
"@layer properties {
5+
@supports (((-webkit-hyphens: none)) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color: rgb(from red r g b)))) {
6+
*, :before, :after, ::backdrop {
7+
--tw-font-weight: initial;
8+
}
9+
}
10+
}
11+
12+
@layer theme {
513
:root, :host {
614
--font-sans: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
715
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
@@ -281,14 +289,6 @@ exports[`\`@import 'tailwindcss'\` is replaced with the generated CSS 1`] = `
281289
}
282290
}
283291
284-
@supports (((-webkit-hyphens: none)) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color: rgb(from red r g b)))) {
285-
@layer base {
286-
*, :before, :after, ::backdrop {
287-
--tw-font-weight: initial;
288-
}
289-
}
290-
}
291-
292292
@property --tw-font-weight {
293293
syntax: "*";
294294
inherits: false

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
22

33
exports[`compiling CSS > \`@tailwind utilities\` is replaced by utilities using the default theme 1`] = `
4-
"@supports (((-webkit-hyphens: none)) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color: rgb(from red r g b)))) {
5-
@layer base {
4+
"@layer properties {
5+
@supports (((-webkit-hyphens: none)) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color: rgb(from red r g b)))) {
66
*, :before, :after, ::backdrop {
77
--tw-shadow: 0 0 #0000;
88
--tw-shadow-color: initial;

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

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
22

33
exports[`border-* 1`] = `
4-
"@supports (((-webkit-hyphens: none)) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color: rgb(from red r g b)))) {
5-
@layer base {
4+
"@layer properties {
5+
@supports (((-webkit-hyphens: none)) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color: rgb(from red r g b)))) {
66
*, :before, :after, ::backdrop {
77
--tw-border-style: solid;
88
}
@@ -175,8 +175,8 @@ exports[`border-* 1`] = `
175175
`;
176176

177177
exports[`border-b-* 1`] = `
178-
"@supports (((-webkit-hyphens: none)) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color: rgb(from red r g b)))) {
179-
@layer base {
178+
"@layer properties {
179+
@supports (((-webkit-hyphens: none)) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color: rgb(from red r g b)))) {
180180
*, :before, :after, ::backdrop {
181181
--tw-border-style: solid;
182182
}
@@ -349,8 +349,8 @@ exports[`border-b-* 1`] = `
349349
`;
350350

351351
exports[`border-e-* 1`] = `
352-
"@supports (((-webkit-hyphens: none)) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color: rgb(from red r g b)))) {
353-
@layer base {
352+
"@layer properties {
353+
@supports (((-webkit-hyphens: none)) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color: rgb(from red r g b)))) {
354354
*, :before, :after, ::backdrop {
355355
--tw-border-style: solid;
356356
}
@@ -523,8 +523,8 @@ exports[`border-e-* 1`] = `
523523
`;
524524

525525
exports[`border-l-* 1`] = `
526-
"@supports (((-webkit-hyphens: none)) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color: rgb(from red r g b)))) {
527-
@layer base {
526+
"@layer properties {
527+
@supports (((-webkit-hyphens: none)) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color: rgb(from red r g b)))) {
528528
*, :before, :after, ::backdrop {
529529
--tw-border-style: solid;
530530
}
@@ -697,8 +697,8 @@ exports[`border-l-* 1`] = `
697697
`;
698698

699699
exports[`border-r-* 1`] = `
700-
"@supports (((-webkit-hyphens: none)) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color: rgb(from red r g b)))) {
701-
@layer base {
700+
"@layer properties {
701+
@supports (((-webkit-hyphens: none)) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color: rgb(from red r g b)))) {
702702
*, :before, :after, ::backdrop {
703703
--tw-border-style: solid;
704704
}
@@ -871,8 +871,8 @@ exports[`border-r-* 1`] = `
871871
`;
872872

873873
exports[`border-s-* 1`] = `
874-
"@supports (((-webkit-hyphens: none)) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color: rgb(from red r g b)))) {
875-
@layer base {
874+
"@layer properties {
875+
@supports (((-webkit-hyphens: none)) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color: rgb(from red r g b)))) {
876876
*, :before, :after, ::backdrop {
877877
--tw-border-style: solid;
878878
}
@@ -1045,8 +1045,8 @@ exports[`border-s-* 1`] = `
10451045
`;
10461046

10471047
exports[`border-t-* 1`] = `
1048-
"@supports (((-webkit-hyphens: none)) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color: rgb(from red r g b)))) {
1049-
@layer base {
1048+
"@layer properties {
1049+
@supports (((-webkit-hyphens: none)) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color: rgb(from red r g b)))) {
10501050
*, :before, :after, ::backdrop {
10511051
--tw-border-style: solid;
10521052
}
@@ -1219,8 +1219,8 @@ exports[`border-t-* 1`] = `
12191219
`;
12201220

12211221
exports[`border-x-* 1`] = `
1222-
"@supports (((-webkit-hyphens: none)) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color: rgb(from red r g b)))) {
1223-
@layer base {
1222+
"@layer properties {
1223+
@supports (((-webkit-hyphens: none)) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color: rgb(from red r g b)))) {
12241224
*, :before, :after, ::backdrop {
12251225
--tw-border-style: solid;
12261226
}
@@ -1393,8 +1393,8 @@ exports[`border-x-* 1`] = `
13931393
`;
13941394

13951395
exports[`border-y-* 1`] = `
1396-
"@supports (((-webkit-hyphens: none)) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color: rgb(from red r g b)))) {
1397-
@layer base {
1396+
"@layer properties {
1397+
@supports (((-webkit-hyphens: none)) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color: rgb(from red r g b)))) {
13981398
*, :before, :after, ::backdrop {
13991399
--tw-border-style: solid;
14001400
}

packages/tailwindcss/src/ast.ts

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,8 @@ export function optimizeAst(
569569
}
570570
}
571571

572+
newAst = newAst.concat(atRoots)
573+
572574
// Fallbacks
573575
if (polyfills & Polyfills.AtProperty) {
574576
let fallbackAst = []
@@ -582,6 +584,9 @@ export function optimizeAst(
582584
}
583585

584586
if (fallbackAst.length > 0) {
587+
// Insert an empty `@layer properties;` at the beginning of the document. We need to place it
588+
// after eventual external imports as `lightningcss` would otherwise move the content into the
589+
// same place.
585590
let firstValidNodeIndex = newAst.findIndex((node) => {
586591
// License comments
587592
if (node.kind === 'comment') return false
@@ -592,9 +597,6 @@ export function optimizeAst(
592597

593598
// External imports
594599
if (node.name === '@import') return false
595-
596-
// Body-less `@layer …;`
597-
if (node.name === '@layer' && node.nodes.length === 0) return false
598600
}
599601

600602
return true
@@ -603,18 +605,24 @@ export function optimizeAst(
603605
newAst.splice(
604606
firstValidNodeIndex < 0 ? newAst.length : firstValidNodeIndex,
605607
0,
606-
atRule(
607-
'@supports',
608-
// We can't write a supports query for `@property` directly so we have to test for
609-
// features that are added around the same time in Mozilla and Safari.
610-
'((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b))))',
611-
[rule('@layer base', fallbackAst)],
612-
),
608+
atRule('@layer', 'properties', []),
609+
)
610+
611+
newAst.push(
612+
rule('@layer properties', [
613+
atRule(
614+
'@supports',
615+
// We can't write a supports query for `@property` directly so we have to test for
616+
// features that are added around the same time in Mozilla and Safari.
617+
'((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b))))',
618+
fallbackAst,
619+
),
620+
]),
613621
)
614622
}
615623
}
616624

617-
return newAst.concat(atRoots)
625+
return newAst
618626
}
619627

620628
export function toCss(ast: AstNode[]) {

packages/tailwindcss/src/compat/config.test.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -322,13 +322,7 @@ describe('theme callbacks', () => {
322322

323323
expect(compiler.build(['leading-base', 'leading-md', 'leading-xl', 'prose']))
324324
.toMatchInlineSnapshot(`
325-
"@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
326-
@layer base {
327-
*, ::before, ::after, ::backdrop {
328-
--tw-leading: initial;
329-
}
330-
}
331-
}
325+
"@layer properties;
332326
.prose {
333327
[class~=lead-base] {
334328
font-size: 100rem;
@@ -359,6 +353,13 @@ describe('theme callbacks', () => {
359353
syntax: "*";
360354
inherits: false;
361355
}
356+
@layer properties {
357+
@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
358+
*, ::before, ::after, ::backdrop {
359+
--tw-leading: initial;
360+
}
361+
}
362+
}
362363
"
363364
`)
364365
})

packages/tailwindcss/src/important.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,8 @@ test('variables in utilities should not be marked as important', async () => {
101101
['ease-out!', 'z-10!'],
102102
),
103103
).toMatchInlineSnapshot(`
104-
"@supports (((-webkit-hyphens: none)) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color: rgb(from red r g b)))) {
105-
@layer base {
104+
"@layer properties {
105+
@supports (((-webkit-hyphens: none)) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color: rgb(from red r g b)))) {
106106
*, :before, :after, ::backdrop {
107107
--tw-ease: initial;
108108
}

0 commit comments

Comments
 (0)