Developers using Next.js with Turbopack, Vite, or templating engines like Pug, Ruby, Slim, or Haml should upgrade to benefit from fixed HMR and improved candidate extraction.
๐ Product & Engineering Leads
This stability release enhances developer productivity and build reliability across modern web frameworks without altering end-user runtime capabilities.
โ๏ธ DevOps & Security
DevOps teams running macOS CI pipelines or non-native architecture builds will benefit from fixed macOS binary signatures and `@tailwindcss/oxide` WASM fallbacks.
โจ New Features & Capabilities (1)
Added `@tailwindcss/turbopack`, a Turbopack loader for using Tailwind CSS with Next.js.
โก Performance & Enhancements (4)
Improved style invalidation performance for `group-*` and `peer-*` variants.
Optimized watch mode by skipping ignored directories during glob generation instead of scanning their contents.
Expanded arbitrary value length parsing to recognize viewport units (`dvmin`, `svi`) and font-relative units (`cap`, `rex`).
Enhanced canonicalization logic to convert arbitrary breakpoint and container queries to named equivalents (e.g., `max-[64rem]:flex` to `max-lg:flex`).
๐ง Bug Fixes & Patches (6)
Fixed binary code signing for standalone macOS binaries to prevent crashes on launch.
Ensured `@tailwindcss/turbopack` and `@tailwindcss/webpack` rebuild when input CSS files change.
Prevented `@tailwindcss/vite` from crashing under Vite's experimental `bundledDev` mode and stopped full-page reloads for non-module files.
Ensured `@tailwindcss/oxide` falls back to WASM on platforms without native bindings.
Fixed candidate extraction for Ruby `%w` and `%W` literals and complex syntax in Pug, Slim, and Haml templates.
Fixed CSS parser handling for unclosed semicolons, comments ending in `\*/`, `!important` within strings, and nested `@scope` semantics.
๐ View Raw Release Notes (Original Developer Log)
### Added
- Add `@tailwindcss/turbopack`, a Turbopack loader for using Tailwind CSS with Next.js ([#20367](https://github.com/tailwindlabs/tailwindcss/pull/20367))
### Fixed
- Ensure watch mode detects changes to symlinked `@source` files whose real paths aren't otherwise scanned ([#20356](https://github.com/tailwindlabs/tailwindcss/pull/20356))
- Ensure variants using `@scope` wrap generated utilities instead of nesting inside them ([#20369](https://github.com/tailwindlabs/tailwindcss/pull/20369))
- Ensure nested `@scope` rules preserve their scoping semantics when flattened ([#20369](https://github.com/tailwindlabs/tailwindcss/pull/20369))
- Preserve declarations directly inside `@scope` by wrapping them in `:where(:scope)` ([#20369](https://github.com/tailwindlabs/tailwindcss/pull/20369))
- Ensure generated utilities include a space in empty `var()` fallbacks (e.g. `var(--tw-blur,)` โ `var(--tw-blur, )`) ([#20373](https://github.com/tailwindlabs/tailwindcss/pull/20373))
- Canonicalization: convert arbitrary breakpoint and container query variants to named equivalents (e.g. `max-[64rem]:flex` โ `max-lg:flex`) ([#20380](https://github.com/tailwindlabs/tailwindcss/pull/20380))
- Prevent `@tailwindcss/vite` from crashing on every edit under Vite's experimental `bundledDev` mode ([#20379](https://github.com/tailwindlabs/tailwindcss/pull/20379))
- Ensure `@tailwindcss/oxide` falls back to WASM on platforms without native bindings ([#20383](https://github.com/tailwindlabs/tailwindcss/pull/20383))
- Extract class candidates from Ruby `%w` and `%W` literals using angle brackets or custom delimiters (e.g. `%w<flex>`, `%w|flex|`), including in Slim and Haml templates ([#20387](https://github.com/tailwindlabs/tailwindcss/pull/20387))
- Preserve whitespace in `--default(โฆ)` values in functional `@utility` definitions (e.g. `--default(box alphabetic)` no longer becomes `boxalphabetic`) ([#20392](https://github.com/tailwindlabs/tailwindcss/pull/20392))
- Ensure automatic source detection respects negation-based `.gitignore` files (e.g. `/*` followed by `!/โฆ` patterns) ([#20397](https://github.com/tailwindlabs/tailwindcss/pull/20397))
- Ensure root `theme('โฆ')` namespace lookups in JavaScript plugins and config files return the full namespace object instead of the value of its `DEFAULT` key ([#20399](https://github.com/tailwindlabs/tailwindcss/pull/20399))
- Skip ignored directories when generating watch globs instead of walking their contents on every rebuild ([#20408](https://github.com/tailwindlabs/tailwindcss/pull/20408))
- Drop invalid UTF-8 candidates during class detection ([#20389](https://github.com/tailwindlabs/tailwindcss/pull/20389))
- Prevent `@tailwindcss/vite` from forcing full-page reloads for scanned files that Vite does not handle as modules (e.g. `.php` files) ([#20414](https://github.com/tailwindlabs/tailwindcss/pull/20414))
- Canonicalization: don't merge utilities that reference different theme variables set to CSS-wide keywords like `unset` ([#20417](https://github.com/tailwindlabs/tailwindcss/pull/20417))
- Don't generate utilities when a modifier is used that would otherwise be silently ignored (e.g. `rounded-sm/[5]`, `shadow-sm/foo`, `stroke-2/50`) ([#20419](https://github.com/tailwindlabs/tailwindcss/pull/20419))
- Preserve `and`, `or`, and `not` inside selectors in `supports-[โฆ]` variants (e.g. `supports-[selector(a:not(.foo))]:flex`) ([#20420](https://github.com/tailwindlabs/tailwindcss/pull/20420))
- Don't warn about Angular's `::ng-deep` and `:host-context()` when optimizing CSS ([#20434](https://github.com/tailwindlabs/tailwindcss/pull/20434))
- Don't generate CSS for candidates containing an empty additional modifier (e.g. `bg-red-500/50/` and `group-hover/foo//bar:flex`) ([#20466](https://github.com/tailwindlabs/tailwindcss/pull/20466))
- Ensure `min-*`, `max-*`, and container query variants with decimal values are sorted numerically (e.g. `min-[40.25rem]` before `min-[40.5rem]`) ([#20512](https://github.com/tailwindlabs/tailwindcss/pull/20512))
- Ensure CSS comments ending with `\*/` are closed correctly instead of swallowing the CSS that follows (e.g. `/* C:\temp\*/`) ([#20508](https://github.com/tailwindlabs/tailwindcss/pull/20508))
- Improve style invalidation performance of `group-*` and `peer-*` variants ([#20513](https://github.com/tailwindlabs/tailwindcss/pull/20513))
- Ensure cached compilers release their `loadModule` and `loadStylesheet` callbacks after compilation ([#20531](https://github.com/tailwindlabs/tailwindcss/pull/20531))
- Canonicalization: preserve `&` when moving a pseudo-element into `*` or `**` (e.g. `[&_::before]:flex` โ `**:[&::before]:flex`) ([#20550](https://github.com/tailwindlabs/tailwindcss/pull/20550))
- Ensure the `Set.prototype.intersection` polyfill in `canonicalizeCandidates(โฆ)` returns the intersection instead of the first set on Node.js < 22 ([#20562](https://github.com/tailwindlabs/tailwindcss/pull/20562))
- Canonicalization: ensure inline `theme(โฆ)` alphas with more than 2 decimals migrate to a percentage modifier with the same opacity (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: preserve 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))
- Write plugin logs to stderr in `tailwindcss canonicalize` so they don't end up in the results on stdout ([#20561](https://github.com/tailwindlabs/tailwindcss/pull/20561))
- Extract class shorthands on later lines when Pug text, comments, or quoted attribute values contain unbalanced brackets, or a quote that doesn't start a string (e.g. `input(pattern=/"/.source)`) ([#20547](https://github.com/tailwindlabs/tailwindcss/pull/20547), [#20572](https://github.com/tailwindlabs/tailwindcss/pull/20572))
- Underline the correct occurrence of an unsupported data type in `--value(โฆ)` warnings ([#20554](https://github.com/tailwindlabs/tailwindcss/pull/20554))
- Canonicalization: prefer an existing candidate when collapsing utilities over another utility with the same default theme value (e.g. `text-foreground text-primary` โ `text-primary`, not `text-card-checked-border`) ([#20540](https://github.com/tailwindlabs/tailwindcss/pull/20540))
- Canonicalization: don't collapse utilities into a utility that uses another theme variable with the same default value (e.g. `mt-card mb-card` โ `my-card`, not `my-4`) ([#20574](https://github.com/tailwindlabs/tailwindcss/pull/20574))
- Ensure `@tailwindcss/postcss` rewrites relative `url(โฆ)`s of stylesheets that are inlined before it runs (e.g. `@import`s in Vite) in optimized builds ([#20576](https://github.com/tailwindlabs/tailwindcss/pull/20576))
- Drop nested rules that put a combinator after a pseudo-element when using pseudo-element variants (e.g. `selection:*` on a utility with a nested `& > *` rule) ([#20575](https://github.com/tailwindlabs/tailwindcss/pull/20575))
- Don't generate CSS for arbitrary values with unbalanced parentheses or brackets (e.g. `w-[calc(1px]` or `[--x:a[b]`) ([#20577](https://github.com/tailwindlabs/tailwindcss/pull/20577))
- Canonicalization: prevent `collapse: true` from taking exponentially longer when classes are linked through a utility that sets many properties (e.g. `sr-only`) ([#20558](https://github.com/tailwindlabs/tailwindcss/pull/20558))
- Ensure `&` is substituted inside `:-moz-any(โฆ)` and `:-webkit-any(โฆ)` in custom variants (e.g. `@custom-variant firefox (:-moz-any(&));`) ([#20486](https://github.com/tailwindlabs/tailwindcss/pull/20486))
- Ensure the standalone macOS binaries have a valid code signature, so macOS 27 no longer kills them at launch ([#20578](https://github.com/tailwindlabs/tailwindcss/pull/20578))
- Ensure `@tailwindcss/turbopack` and `@tailwindcss/webpack` rebuild when the input CSS changes (e.g. `next dev` with Turbopack no longer serves the CSS of the previous edit) ([#20582](https://github.com/tailwindlabs/tailwindcss/pull/20582))
- Canonicalization: don't drop a utility that sets a `--tw-*` variable when an unrelated property has the same value (e.g. `link mt-4` no longer becomes `mt-4` when `link` sets `margin-top: 16px` and `--tw-translate-x: 16px`) ([#20593](https://github.com/tailwindlabs/tailwindcss/pull/20593))
- Decode single-digit hexadecimal escapes in theme variable and `@utility` names as the CSS spec does (e.g. `@theme { --color-\0: red; }` no longer registers `--color-0`) ([#20591](https://github.com/tailwindlabs/tailwindcss/pull/20591))
- Don't treat `!important` inside strings, comments or `url()` in declaration values as the important flag (e.g. `content: "a !important b"`) ([#20627](https://github.com/tailwindlabs/tailwindcss/pull/20627))
- Parse a custom property at the end of the input when it has no trailing `;` (e.g. `--foo: bar` as the last declaration) ([#20653](https://github.com/tailwindlabs/tailwindcss/pull/20653))
- Keep a declaration without a `;` at the end of the CSS input (e.g. `color: red`) ([#20655](https://github.com/tailwindlabs/tailwindcss/pull/20655))