diff --git a/CHANGELOG.md b/CHANGELOG.md
index a345e26cd821..e913c18695e4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -56,6 +56,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Rename `--transition-timing-function-*` variables to `--ease-*` ([#14886](https://github.com/tailwindlabs/tailwindcss/pull/14886))
- Rename `--width-*` variables to `--container-*` ([#14898](https://github.com/tailwindlabs/tailwindcss/pull/14898))
- Rename `--font-size-*` variables to `--text-*` ([#14909](https://github.com/tailwindlabs/tailwindcss/pull/14909))
+- Rename `--letter-spacing-*` variables to `--tracking-*` ([#14921](https://github.com/tailwindlabs/tailwindcss/pull/14921))
- Revert specificity of `*` variant to match v3 behavior ([#14920](https://github.com/tailwindlabs/tailwindcss/pull/14920))
## [4.0.0-alpha.31] - 2024-10-29
diff --git a/integrations/upgrade/js-config.test.ts b/integrations/upgrade/js-config.test.ts
index 5db64a52bb1e..889c13cc9104 100644
--- a/integrations/upgrade/js-config.test.ts
+++ b/integrations/upgrade/js-config.test.ts
@@ -114,6 +114,9 @@ test(
'spin-clockwise': 'spin-clockwise 1s linear infinite',
'spin-counterclockwise': 'spin-counterclockwise 1s linear infinite',
},
+ letterSpacing: {
+ superWide: '0.25em',
+ },
},
},
plugins: [],
@@ -130,6 +133,11 @@ test(
'shouldNotMigrate': !border.test + '',
}
`,
+ 'src/index.html': html`
+
Hello world!
@@ -140,8 +148,13 @@ test(
async ({ exec, fs }) => {
await exec('npx @tailwindcss/upgrade')
- expect(await fs.dumpFiles('src/**/*.{css,js}')).toMatchInlineSnapshot(`
+ expect(await fs.dumpFiles('src/**/*.{css,js,html}')).toMatchInlineSnapshot(`
"
+ --- src/index.html ---
+
+
--- src/input.css ---
@import 'tailwindcss';
@@ -223,6 +236,8 @@ test(
--animate-spin-clockwise: spin-clockwise 1s linear infinite;
--animate-spin-counterclockwise: spin-counterclockwise 1s linear infinite;
+ --tracking-super-wide: 0.25em;
+
@keyframes spin-clockwise {
0% {
transform: rotate(0deg);
diff --git a/packages/@tailwindcss-postcss/src/__snapshots__/index.test.ts.snap b/packages/@tailwindcss-postcss/src/__snapshots__/index.test.ts.snap
index ad9c3ff71f41..b3ae33f3552b 100644
--- a/packages/@tailwindcss-postcss/src/__snapshots__/index.test.ts.snap
+++ b/packages/@tailwindcss-postcss/src/__snapshots__/index.test.ts.snap
@@ -349,12 +349,12 @@ exports[`\`@import 'tailwindcss'\` is replaced with the generated CSS 1`] = `
--font-weight-bold: 700;
--font-weight-extrabold: 800;
--font-weight-black: 900;
- --letter-spacing-tighter: -.05em;
- --letter-spacing-tight: -.025em;
- --letter-spacing-normal: 0em;
- --letter-spacing-wide: .025em;
- --letter-spacing-wider: .05em;
- --letter-spacing-widest: .1em;
+ --tracking-tighter: -.05em;
+ --tracking-tight: -.025em;
+ --tracking-normal: 0em;
+ --tracking-wide: .025em;
+ --tracking-wider: .05em;
+ --tracking-widest: .1em;
--line-height-none: 1;
--line-height-tight: 1.25;
--line-height-snug: 1.375;
diff --git a/packages/tailwindcss/src/__snapshots__/index.test.ts.snap b/packages/tailwindcss/src/__snapshots__/index.test.ts.snap
index 760d4a9ec6f5..7426fef22528 100644
--- a/packages/tailwindcss/src/__snapshots__/index.test.ts.snap
+++ b/packages/tailwindcss/src/__snapshots__/index.test.ts.snap
@@ -348,12 +348,12 @@ exports[`compiling CSS > \`@tailwind utilities\` is replaced by utilities using
--font-weight-bold: 700;
--font-weight-extrabold: 800;
--font-weight-black: 900;
- --letter-spacing-tighter: -.05em;
- --letter-spacing-tight: -.025em;
- --letter-spacing-normal: 0em;
- --letter-spacing-wide: .025em;
- --letter-spacing-wider: .05em;
- --letter-spacing-widest: .1em;
+ --tracking-tighter: -.05em;
+ --tracking-tight: -.025em;
+ --tracking-normal: 0em;
+ --tracking-wide: .025em;
+ --tracking-wider: .05em;
+ --tracking-widest: .1em;
--line-height-none: 1;
--line-height-tight: 1.25;
--line-height-snug: 1.375;
diff --git a/packages/tailwindcss/src/compat/apply-config-to-theme.test.ts b/packages/tailwindcss/src/compat/apply-config-to-theme.test.ts
index 9a44a1719d06..1d16ed8108ae 100644
--- a/packages/tailwindcss/src/compat/apply-config-to-theme.test.ts
+++ b/packages/tailwindcss/src/compat/apply-config-to-theme.test.ts
@@ -50,6 +50,10 @@ test('config values can be merged into the theme', () => {
],
},
+ letterSpacing: {
+ superWide: '0.25em',
+ },
+
width: {
// Purposely setting to something different from the default
'1/2': '60%',
@@ -88,6 +92,7 @@ test('config values can be merged into the theme', () => {
'1rem',
{ '--line-height': '1.5' },
])
+ expect(theme.resolve('super-wide', ['--tracking'])).toEqual('0.25em')
expect(theme.resolve('1/2', ['--width'])).toEqual('60%')
expect(theme.resolve('0.5', ['--width'])).toEqual('60%')
expect(theme.resolve('100%', ['--width'])).toEqual('100%')
diff --git a/packages/tailwindcss/src/compat/apply-config-to-theme.ts b/packages/tailwindcss/src/compat/apply-config-to-theme.ts
index 22e658ac78af..a5940cb3982d 100644
--- a/packages/tailwindcss/src/compat/apply-config-to-theme.ts
+++ b/packages/tailwindcss/src/compat/apply-config-to-theme.ts
@@ -130,15 +130,16 @@ const IS_VALID_KEY = /^[a-zA-Z0-9-_%/\.]+$/
export function keyPathToCssProperty(path: string[]) {
path = structuredClone(path)
- if (path[0] === 'colors') path[0] = 'color'
- if (path[0] === 'screens') path[0] = 'breakpoint'
+ if (path[0] === 'animation') path[0] = 'animate'
if (path[0] === 'borderRadius') path[0] = 'radius'
if (path[0] === 'boxShadow') path[0] = 'shadow'
- if (path[0] === 'animation') path[0] = 'animate'
- if (path[0] === 'transitionTimingFunction') path[0] = 'ease'
+ if (path[0] === 'colors') path[0] = 'color'
if (path[0] === 'fontFamily') path[0] = 'font'
if (path[0] === 'fontSize') path[0] = 'text'
+ if (path[0] === 'letterSpacing') path[0] = 'tracking'
if (path[0] === 'maxWidth') path[0] = 'container'
+ if (path[0] === 'screens') path[0] = 'breakpoint'
+ if (path[0] === 'transitionTimingFunction') path[0] = 'ease'
for (let part of path) {
if (!IS_VALID_KEY.test(part)) return null
diff --git a/packages/tailwindcss/src/compat/config.test.ts b/packages/tailwindcss/src/compat/config.test.ts
index 6bc18aae5afa..6b2e89ccff48 100644
--- a/packages/tailwindcss/src/compat/config.test.ts
+++ b/packages/tailwindcss/src/compat/config.test.ts
@@ -1536,6 +1536,9 @@ test('old theme values are merged with their renamed counterparts in the CSS the
--container-a: 1;
--container-b: 2;
+
+ --tracking-a: 1;
+ --tracking-b: 2;
}
@plugin "./plugin.js";
@@ -1594,6 +1597,14 @@ test('old theme values are merged with their renamed counterparts in the CSS the
expect(theme('maxWidth.a')).toEqual('1')
expect(theme('maxWidth.b')).toEqual('2')
+
+ expect(theme('letterSpacing.a')).toEqual('1')
+ expect(theme('letterSpacing.b')).toEqual('2')
+
+ expect(theme('letterSpacing')).toMatchObject({
+ a: '1',
+ b: '2',
+ })
}),
}
},
diff --git a/packages/tailwindcss/src/compat/config/create-compat-config.ts b/packages/tailwindcss/src/compat/config/create-compat-config.ts
index 5258eec24214..33fcc45bab61 100644
--- a/packages/tailwindcss/src/compat/config/create-compat-config.ts
+++ b/packages/tailwindcss/src/compat/config/create-compat-config.ts
@@ -34,6 +34,10 @@ export function createCompatConfig(cssTheme: Theme): UserConfig {
...theme('breakpoint', {}),
}),
+ letterSpacing: ({ theme }) => ({
+ ...theme('tracking', {}),
+ }),
+
transitionDuration: {
DEFAULT: cssTheme.get(['--default-transition-duration']) ?? null,
},
diff --git a/packages/tailwindcss/src/css-functions.test.ts b/packages/tailwindcss/src/css-functions.test.ts
index db0d523a77c6..d4bf15fd7619 100644
--- a/packages/tailwindcss/src/css-functions.test.ts
+++ b/packages/tailwindcss/src/css-functions.test.ts
@@ -639,6 +639,7 @@ describe('theme function', () => {
],
['maxWidth.xs', '20rem'],
['transitionTimingFunction.in-out', 'cubic-bezier(.4, 0, .2, 1)'],
+ ['letterSpacing.wide', '.025em'],
['backgroundColor.red.500', 'oklch(.637 .237 25.331)'],
])('theme(%s) → %s', async (value, result) => {
let defaultTheme = await fs.readFile(path.join(__dirname, '..', 'theme.css'), 'utf8')
diff --git a/packages/tailwindcss/src/utilities.test.ts b/packages/tailwindcss/src/utilities.test.ts
index 911eedb06908..bc7dcaf474c5 100644
--- a/packages/tailwindcss/src/utilities.test.ts
+++ b/packages/tailwindcss/src/utilities.test.ts
@@ -14095,8 +14095,8 @@ test('tracking', async () => {
await compileCss(
css`
@theme {
- --letter-spacing-normal: 0em;
- --letter-spacing-wide: 0.025em;
+ --tracking-normal: 0em;
+ --tracking-wide: 0.025em;
}
@tailwind utilities;
`,
@@ -14104,8 +14104,8 @@ test('tracking', async () => {
),
).toMatchInlineSnapshot(`
":root {
- --letter-spacing-normal: 0em;
- --letter-spacing-wide: .025em;
+ --tracking-normal: 0em;
+ --tracking-wide: .025em;
}
.-tracking-\\[var\\(--value\\)\\] {
@@ -14119,13 +14119,13 @@ test('tracking', async () => {
}
.tracking-normal {
- --tw-tracking: var(--letter-spacing-normal);
- letter-spacing: var(--letter-spacing-normal);
+ --tw-tracking: var(--tracking-normal);
+ letter-spacing: var(--tracking-normal);
}
.tracking-wide {
- --tw-tracking: var(--letter-spacing-wide);
- letter-spacing: var(--letter-spacing-wide);
+ --tw-tracking: var(--tracking-wide);
+ letter-spacing: var(--tracking-wide);
}
@supports (-moz-orient: inline) {
diff --git a/packages/tailwindcss/src/utilities.ts b/packages/tailwindcss/src/utilities.ts
index d261273fbe7e..671719d96e39 100644
--- a/packages/tailwindcss/src/utilities.ts
+++ b/packages/tailwindcss/src/utilities.ts
@@ -3617,7 +3617,7 @@ export function createUtilities(theme: Theme) {
functionalUtility('tracking', {
supportsNegative: true,
- themeKeys: ['--letter-spacing'],
+ themeKeys: ['--tracking'],
handle: (value) => [
atRoot([property('--tw-tracking')]),
decl('--tw-tracking', value),
@@ -3911,7 +3911,7 @@ export function createUtilities(theme: Theme) {
let value = theme.resolveWith(
candidate.value.value,
['--text'],
- ['--line-height', '--letter-spacing', '--font-weight'],
+ ['--line-height', '--tracking', '--font-weight'],
)
if (value) {
let [fontSize, options = {}] = Array.isArray(value) ? value : [value]
@@ -3939,8 +3939,8 @@ export function createUtilities(theme: Theme) {
),
decl(
'letter-spacing',
- options['--letter-spacing']
- ? `var(--tw-tracking, ${options['--letter-spacing']})`
+ options['--tracking']
+ ? `var(--tw-tracking, ${options['--tracking']})`
: undefined,
),
decl(
diff --git a/packages/tailwindcss/tests/ui.spec.ts b/packages/tailwindcss/tests/ui.spec.ts
index b8e7a6c8e0a0..b5ce446b2a8b 100644
--- a/packages/tailwindcss/tests/ui.spec.ts
+++ b/packages/tailwindcss/tests/ui.spec.ts
@@ -568,9 +568,9 @@ test('explicit tracking utilities are respected when overriding font-size', asyn
`,
css`
@theme {
- --text-sm--letter-spacing: 5px;
- --text-xl--letter-spacing: 10px;
- --letter-spacing-tight: 1px;
+ --text-sm--tracking: 5px;
+ --text-xl--tracking: 10px;
+ --tracking-tight: 1px;
}
`,
)
diff --git a/packages/tailwindcss/theme.css b/packages/tailwindcss/theme.css
index ba6d9a538c64..32ccf854fbf6 100644
--- a/packages/tailwindcss/theme.css
+++ b/packages/tailwindcss/theme.css
@@ -397,13 +397,13 @@
--font-weight-extrabold: 800;
--font-weight-black: 900;
- /* Letter spacing */
- --letter-spacing-tighter: -0.05em;
- --letter-spacing-tight: -0.025em;
- --letter-spacing-normal: 0em;
- --letter-spacing-wide: 0.025em;
- --letter-spacing-wider: 0.05em;
- --letter-spacing-widest: 0.1em;
+ /* Tracking */
+ --tracking-tighter: -0.05em;
+ --tracking-tight: -0.025em;
+ --tracking-normal: 0em;
+ --tracking-wide: 0.025em;
+ --tracking-wider: 0.05em;
+ --tracking-widest: 0.1em;
/* Line-height */
--line-height-none: 1;