Recognize missing viewport and font-relative length units (#20516)

## Summary

`isLength` in `packages/tailwindcss/src/utils/infer-data-type.ts` checks
arbitrary values against a fixed list of units. That list was carried
over from v3 and is missing several CSS length units: the small, large,
and dynamic viewport units `svi`, `svb`, `svmin`, `svmax`, `lvi`, `lvb`,
`lvmin`, `lvmax`, `dvi`, `dvb`, `dvmin`, `dvmax`, and the font-relative
units `cap`, `ic`, `rex`, `rch`, `rcap`, `ric`.

Because these values are not detected as lengths, utilities that choose
a property based on the value type fall back to the color branch. For
example `text-[10dvmin]` generates `color: 10dvmin` instead of
`font-size: 10dvmin` (while `text-[10dvw]` already works), and
`border-[1dvmin]` generates `border-color: 1dvmin`. Today the only
workaround is an explicit type hint like `text-[length:10dvmin]`.

This adds the missing units, all of which are `<length>` units defined
in CSS Values and Units Level 4, to the list. Values that were already
detected are unaffected.

## Test plan

- Added a test to `packages/tailwindcss/src/utilities.test.ts` that
compiles `text-[1<unit>]` for each of the 18 new units and compares the
full generated rule. It fails without the change (the rules are emitted
as `color: 1<unit>`) and passes with it.
- `vitest run src/utilities.test.ts -t "viewport and font-relative"` (in
`packages/tailwindcss`)
- `vitest run` (in `packages/tailwindcss`): 42 files, 5016 tests passed
- `prettier --check` on the changed files

---------

Co-authored-by: Robin Malfait <robin.malfait@shopify.com>
This commit is contained in:
Alexandre KohlerandRobin Malfait authored and GitHub committed 2026-10-13 13:17:03 +00:00
1 parent 931db16192
commit 9833b487a8
3 files changed
+109

No files matched your search

+1
View File
@@ -42,6 +42,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Canonicalization: fix inline `theme(…)` alphas with more than 2 decimals being migrated to a modifier that changes the opacity by a factor of 100 (e.g. `theme(colors.red.500/.12345)` → `text-red-500/[12.345%]`, not `text-red-500/[12.345]`) ([#20563](https://github.com/tailwindlabs/tailwindcss/pull/20563))
- Canonicalization: keep inline `theme(…)` alphas as an arbitrary percentage when a custom `--opacity-*` theme value would change the opacity (e.g. `theme(colors.red.500/50%)` → `text-red-500/[50%]` with `--opacity-50: 10%`) ([#20563](https://github.com/tailwindlabs/tailwindcss/pull/20563))
- Ensure the `@property` fallback isn't applied in Safari versions that no longer support `margin-trim: inline` ([#20569](https://github.com/tailwindlabs/tailwindcss/pull/20569))
- Treat viewport units like `dvmin` and `svi` and font-relative units like `cap` and `rex` as lengths in arbitrary values (e.g. `text-[10dvmin]` generates `font-size` instead of `color`) ([#20516](https://github.com/tailwindlabs/tailwindcss/pull/20516))
## [4.3.3] - 2026-07-16
@@ -26576,6 +26576,24 @@ test('text', async () => {
'text-[clamp(1rem,var(--size),3rem)]',
'text-[clamp(1rem,var(--size),3rem)]/9',
'text-[--spacing(2)]',
'text-[1cap]',
'text-[1ic]',
'text-[1rex]',
'text-[1rch]',
'text-[1rcap]',
'text-[1ric]',
'text-[1svi]',
'text-[1svb]',
'text-[1svmin]',
'text-[1svmax]',
'text-[1lvi]',
'text-[1lvb]',
'text-[1lvmin]',
'text-[1lvmax]',
'text-[1dvi]',
'text-[1dvb]',
'text-[1dvmin]',
'text-[1dvmax]',
],
css`
@theme {
@@ -26669,6 +26687,78 @@ test('text', async () => {
font-size: calc(var(--spacing) * 2);
}
.text-\\[1cap\\] {
font-size: 1cap;
}
.text-\\[1dvb\\] {
font-size: 1dvb;
}
.text-\\[1dvi\\] {
font-size: 1dvi;
}
.text-\\[1dvmax\\] {
font-size: 1dvmax;
}
.text-\\[1dvmin\\] {
font-size: 1dvmin;
}
.text-\\[1ic\\] {
font-size: 1ic;
}
.text-\\[1lvb\\] {
font-size: 1lvb;
}
.text-\\[1lvi\\] {
font-size: 1lvi;
}
.text-\\[1lvmax\\] {
font-size: 1lvmax;
}
.text-\\[1lvmin\\] {
font-size: 1lvmin;
}
.text-\\[1rcap\\] {
font-size: 1rcap;
}
.text-\\[1rch\\] {
font-size: 1rch;
}
.text-\\[1rex\\] {
font-size: 1rex;
}
.text-\\[1ric\\] {
font-size: 1ric;
}
.text-\\[1svb\\] {
font-size: 1svb;
}
.text-\\[1svi\\] {
font-size: 1svi;
}
.text-\\[1svmax\\] {
font-size: 1svmax;
}
.text-\\[1svmin\\] {
font-size: 1svmin;
}
.text-\\[12px\\] {
font-size: 12px;
}
@@ -208,7 +208,13 @@ const LENGTH_UNITS = [
'em',
'ex',
'ch',
'cap',
'ic',
'rem',
'rex',
'rch',
'rcap',
'ric',
'lh',
'rlh',
'vw',
@@ -219,10 +225,22 @@ const LENGTH_UNITS = [
'vi',
'svw',
'svh',
'svi',
'svb',
'svmin',
'svmax',
'lvw',
'lvh',
'lvi',
'lvb',
'lvmin',
'lvmax',
'dvw',
'dvh',
'dvi',
'dvb',
'dvmin',
'dvmax',
'cqw',
'cqh',
'cqi',