This PR improves colors with alpha values where the alpha value results
in 100%.
Before this change, a class like `bg-red-500/100` would be generated as:
```css
.bg-red-500\/100 {
background-color: #ef4444;
}
@supports (color: color-mix(in lab, red, red)) {
.bg-red-500\/100 {
background-color: color-mix(in oklab, var(--color-red-500) 100%, transparent);
}
}
```
But we don't need the `color-mix`, or the fallback styles at all in case
the alpha value is 100%.
After this change the `bg-red-500/100` class will generate as:
```css
.bg-red-500\/100 {
background-color: var(--color-red-500);
}
```
Which is essentially the same as `bg-red-500`, but we can migrate that
away in the future. At least the generated CSS is smaller.
## Test plan
1. Added a test to ensure the generated value doesn't include color-mix
at all.
While working on another PR I noticed that some variants were re-printed
in an odd way.
Specifically, this PR fixes an issue where variants using the `@`-root
were incorrectly printed.
- `@lg` was printed as `@-lg`
- `@[400px]` was printed as `@-[400px]`
This is now special cased where the `-` is not inserted for `@`-root
variants.
## Test plan
1. Added a test to ensure the `@`-root variants are printed correctly.
This PR adds the following utilities that can be used to match an
elements line height:
- `h-lh`
- `min-h-lh`
- `max-h-lh`
These are all equivalent to providing `1lh` as an arbitrary value. e.g.
`h-[1lh]`
Closes#17295
This commit addresses an issue where the PostCSS plugin would get stuck
in an error state when processing files with e.g. invalid @apply
directives.
This change prevents the PostCSS plugin from getting stuck in an error
states particularly when the error happened inside an `@import`ed CSS
files (as these were not registered as dependencies correctly before).
## Error overlays
Some frameworks (e.g. Angular 19 or Next.js) handle errors inside
PostCSS transforms to render a nice error overlay. This works well and
gives immediate feedback that something went wrong. However, even when
dependencies are registered before an error is thrown, these frameworks
_will not consider changes to these dependencies anymore_ when an error
occurs, as you can see in this Next.js example:
https://github.com/user-attachments/assets/985c9dd7-daf8-4628-b4ad-6543ef220954
To avoid conditions where errors are not recoverable, this PR makes it
so that these overlays will no longer show up in the app and only be
logged to the output console. This will need follow-up upstream work
before we can revisit this.
## Test plan
- Tested with the repro in #17295. The error can now be recovered from.
- Tested with a Next.js app where the issue in the screencast above is
now no longer happening.
- Added an integration test for errors in `@import`-ed files
- Added a unit test for the changed `@apply` behavior.
This PR bumps all Tailwind CSS related dependencies when running the
upgrade tool _if_ the dependency exists in your package.json file.
E.g.: if you have `tailwindcss` and `@tailwindcss/vite` in your
package.json, then both will be updated to the latest version.
This PR is not trying to be smart and skip updating if you are already
on the latest version. It will just try and update the dependencies and
your package manager will do nothing in case it was already the latest
version.
## Test plan
Ran this on one of my personal projects and this was the output:
<img width="1023" alt="image"
src="https://github.com/user-attachments/assets/a189fe7a-a58a-44aa-9246-b720e7a2a892"
/>
Notice that I don't have `@tailwindcss/vite` logs because I am using
`@tailwindcss/postcss`.
This PR ensures that the `@tailwindcss/upgrade` tool works on existing
Tailwind CSS v4 projects. This PR also ensures that the upgrade tool is
idempotent, meaning that it can be run multiple times and it should
result in the same output.
One awesome feature this unlocks is that you can run the upgrade tool on
your codebase at any time and upgrade classes if you still have some
legacy syntaxes, such as `bg-[var(--my-color)]`, in your muscle memory.
One small note: If something changed in the first run, re-running will
not work immediately because your git repository will not be clean and
the upgrade tool requires your git repo to be clean. But once you
verified and committed your changes, the upgrade tool will be
idempotent.
Idempotency is guaranteed by ensuring that some migrations are skipped
by checking what version of Tailwind CSS you are on _before_ the version
is upgraded.
For the Tailwind CSS version: We will resolve `tailwindcss` itself to
know the _actual_ version that is installed (the one resolved from
`node_modules`). Not the one available in your package.json. Your
`package.json` could be out of sync if you reverted changes but didn't
run `npm install` yet.
Back to Idempotency:
For example, we have migrations where we change the variant order of
stacked variants. If we would run these migrations every time you run
the upgrade tool then we would be flip-flopping the order every run.
See: https://tailwindcss.com/docs/upgrade-guide#variant-stacking-order
Another example is where we rename some utilities. For example, we
rename:
| Before | After |
| ----------- | ----------- |
| `shadow` | `shadow-sm` |
| `shadow-sm` | `shadow-xs` |
Notice how we have `shadow-sm` in both the `before` and `after` column.
If we would run the upgrade tool again, then we would eventually migrate
your original `shadow` to `shadow-sm` (first run) and then to
`shadow-xs` (second run). Which would result in the wrong shadow.
See: https://tailwindcss.com/docs/upgrade-guide#renamed-utilities
---
The order of upgrade steps changed a bit as well to make the internals
are easier to work with and reason about.
1. Find CSS files
2. Link JS config files (if you are in a Tailwind CSS v3 project)
3. Migrate the JS config files (if you are in a Tailwind CSS v3 project)
4. Upgrade Tailwind CSS to v4 (or the latest version at that point)
5. Migrate the stylesheets (we used to migrate the source files first)
6. Migrate the source files
This is done so that step 5 and 6 will always operate on a Tailwind CSS
v4 project and we don't need to check the version number again. This is
also necessary because your CSS file will now very likely contain
`@import "tailwindcss";` which doesn't exist in Tailwind CSS v3.
This also means that we can rely on the same internals that Tailwind CSS
actually uses for locating the source files. We will use
`@tailwindcss/oxide`'s scanner to find the source files (and it also
keeps your custom `@source` directives into account).
This PR also introduces a few actual migrations related to recent
features and changes we shipped.
1. We migrate deprecated classes to their new names:
| Before | After |
| --------------------- | --------------------- |
| `bg-left-top` | `bg-top-left` |
| `bg-left-bottom` | `bg-bottom-left` |
| `bg-right-top` | `bg-top-right` |
| `bg-right-bottom` | `bg-bottom-right` |
| `object-left-top` | `object-top-left` |
| `object-left-bottom` | `object-bottom-left` |
| `object-right-top` | `object-top-right` |
| `object-right-bottom` | `object-bottom-right` |
Introduced in:
- https://github.com/tailwindlabs/tailwindcss/pull/17378
- https://github.com/tailwindlabs/tailwindcss/pull/17437
2. We migrate simple arbitrary variants to their dedicated variant:
| Before | After |
| ----------------------- | ------------------- |
| `[&:user-valid]:flex` | `user-valid:flex` |
| `[&:user-invalid]:flex` | `user-invalid:flex` |
Introduced in:
- https://github.com/tailwindlabs/tailwindcss/pull/12370
3. We migrate `@media` variants to their dedicated variant:
| Before | After |
| ----------------------------------------------------- |
------------------------- |
| `[@media_print]:flex` | `print:flex` |
| `[@media(prefers-reduced-motion:no-preference)]:flex` |
`motion-safe:flex` |
| `[@media(prefers-reduced-motion:reduce)]:flex` | `motion-reduce:flex`
|
| `[@media(prefers-contrast:more)]:flex` | `contrast-more:flex` |
| `[@media(prefers-contrast:less)]:flex` | `contrast-less:flex` |
| `[@media(orientation:portrait)]:flex` | `portrait:flex` |
| `[@media(orientation:landscape)]:flex` | `landscape:flex` |
| `[@media(forced-colors:active)]:flex` | `forced-colors:flex` |
| `[@media(inverted-colors:inverted)]:flex` | `inverted-colors:flex` |
| `[@media(pointer:none)]:flex` | `pointer-none:flex` |
| `[@media(pointer:coarse)]:flex` | `pointer-coarse:flex` |
| `[@media(pointer:fine)]:flex` | `pointer-fine:flex` |
| `[@media(any-pointer:none)]:flex` | `any-pointer-none:flex` |
| `[@media(any-pointer:coarse)]:flex` | `any-pointer-coarse:flex` |
| `[@media(any-pointer:fine)]:flex` | `any-pointer-fine:flex` |
| `[@media(scripting:none)]:flex` | `noscript:flex` |
The new variants related to `inverted-colors`, `pointer`, `any-pointer`
and `scripting` were introduced in:
- https://github.com/tailwindlabs/tailwindcss/pull/11693
- https://github.com/tailwindlabs/tailwindcss/pull/16946
- https://github.com/tailwindlabs/tailwindcss/pull/11929
- https://github.com/tailwindlabs/tailwindcss/pull/17431
This also applies to the `not` case, e.g.:
| Before | After |
| --------------------------------------------------------- |
----------------------------- |
| `[@media_not_print]:flex` | `not-print:flex` |
| `[@media_not(prefers-reduced-motion:no-preference)]:flex` |
`not-motion-safe:flex` |
| `[@media_not(prefers-reduced-motion:reduce)]:flex` |
`not-motion-reduce:flex` |
| `[@media_not(prefers-contrast:more)]:flex` | `not-contrast-more:flex`
|
| `[@media_not(prefers-contrast:less)]:flex` | `not-contrast-less:flex`
|
| `[@media_not(orientation:portrait)]:flex` | `not-portrait:flex` |
| `[@media_not(orientation:landscape)]:flex` | `not-landscape:flex` |
| `[@media_not(forced-colors:active)]:flex` | `not-forced-colors:flex` |
| `[@media_not(inverted-colors:inverted)]:flex` |
`not-inverted-colors:flex` |
| `[@media_not(pointer:none)]:flex` | `not-pointer-none:flex` |
| `[@media_not(pointer:coarse)]:flex` | `not-pointer-coarse:flex` |
| `[@media_not(pointer:fine)]:flex` | `not-pointer-fine:flex` |
| `[@media_not(any-pointer:none)]:flex` | `not-any-pointer-none:flex` |
| `[@media_not(any-pointer:coarse)]:flex` |
`not-any-pointer-coarse:flex` |
| `[@media_not(any-pointer:fine)]:flex` | `not-any-pointer-fine:flex` |
| `[@media_not(scripting:none)]:flex` | `not-noscript:flex` |
For each candidate, we run a set of upgrade migrations. If at the end of
the migrations the original candidate is still the same as the new
candidate, then we will parse & print the candidate one more time to
pretty print into consistent classes. Luckily parsing is cached so there
is no real downside overhead.
Consistency (especially with arbitrary variants and values) will reduce
your CSS file because there will be fewer "versions" of your class.
Concretely, the pretty printing will apply changes such as:
| Before | After |
| ---------------------- | ----------------- |
| `bg-[var(--my-color)]` | `bg-(--my-color)` |
| `bg-[rgb(0,_0,_0)]` | `bg-[rgb(0,0,0)]` |
Another big important reason for this change is that these classes on
their own
would have been migrated _if_ another migration was relevant for this
candidate.
This means that there are were some inconsistencies. E.g.:
| Before | After | Reason |
| ----------------------- | ---------------------- |
------------------------------------ |
| `!bg-[var(--my-color)]` | `bg-(--my-color)!` | Because the `!` is in
the wrong spot |
| `bg-[var(--my-color)]` | `bg-[var(--my-color)]` | Because no
migrations rand |
As you can see, the way the `--my-color` variable is used, is different.
This
changes will make sure it will now always be consistent:
| Before | After |
| ----------------------- | ---------------------- |
| `!bg-[var(--my-color)]` | `bg-(--my-color)!` |
| `bg-[var(--my-color)]` | `bg-(--my-color)` |
Yay!
Of course, if you don't want these more cosmetic changes, you can always
ignore the upgrade and revert these changes and only commit the changes
you want.
# Test plan
- All existing tests still pass.
- But I had to delete 1 test (we tested that Tailwind CSS v3 was
required).
- And had to mock the `version.isMajor` call to ensure we run the
individual migration tests correctly.
- Added new tests to test:
1. Migrating Tailwind CSS v4 projects works
1. Idempotency of the upgrade tool
[ci-all]
This PR ignores `.db` files by default. We already ignored `.sqlite` and
`.sqlite3` files but we didn't ignore `.db` files which is a common
extension for database files as well.
Due to the binary nature of `.db` files, scanning these could result in
hard to debug errors such as:

Fixes
https://github.com/tailwindlabs/tailwindcss-intellisense/issues/1328
The alpha and beta releases used `_` in theme keys to represent a `.`.
This meant we used `--leading-1_5` instead of `--leading-1\.5` to add
utilities like `leading-1.5`. We prefer the use of the escaped dot now
but still want to make sure suggestions for the legacy key format still
works as expected when surrounded by numbers.
This is the same as #16433 but for `@utility` since we apparently missed
this when emitting suggestions for it
Right now if you have a completely empty theme we'll still suggest
`shadow`, `inset-shadow`, and `text-shadow` as utilities even tho they
won't exist. This fixes this by checking for the theme key when
computing the suggestions.
Resolves https://github.com/tailwindlabs/tailwindcss/issues/17699
GeoJSON files are giant JSON files for geographic data structures and
will never contain Tailwind classes, but because they are often huge
they will slow down the build a lot if scanned.
---------
Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
We generate a glob to ignore binary extensions that looks something like
this:
```
*.{mp4,pages,exe,…}
```
However, if you have a folder that happens to end in `.pages` for
example, then this folder will be ignored in its entirety.
To solve this, we added a new flag to the `Gitignore` struct so we can
register a bunch of ignore rules that _only_ apply to paths and not
folders.
Fixes: #17569
## Test plan
- Added a unit test
---------
Co-authored-by: Philipp Spiess <hello@philippspiess.com>
To publish the newly adde WASM builds, we rely on the
`node-linker=hoisted` `.npmrc` flag that isn't read when `pnpm
--recursive` is used. To work around it, this PR excludes the wasm
package from the `--recursive` part and manually published it
afterwards.
## Test Plan
Ensured this does not error now when trying a `--dry run`.
<img width="1273" alt="Screenshot 2025-04-11 at 17 43 38"
src="https://github.com/user-attachments/assets/68a28552-0125-4da1-92ff-74e58368abe4"
/>
Closes#17448Closes#13133
This PR adds an a new Oxide target for `wasm32-wasip1-threads`:
`@tailwindcss/oxide-wasm32-wasi`. The goal of this is to enable more
environments to run Oxide, including (but not limited to) StackBlitz.
We're making use of `napi-rs`'s upcoming v3 features to simplify the
setup here, meaning `napi-rs` will configure the WASM target and create
an npm package that works across Node and browser environments.
## MacOS AArch64 issues
While setting up an integration test for the new WASM target, I ran into
an issue where FS reads where not terminating on macOS. After some
research I found this to be a limitation of the Node.js container
interface right now, see: https://github.com/nodejs/node/issues/47193
### Windows issues
We also found that the Node.js wasi container does not properly support
Windows: https://github.com/nodejs/uvwasi/issues/11
For now we, it's probably best for MacOS AArch64 users and Windows users
to use the native modules instead.
## Test plan
The `@tailwindcss/oxide-wasm32-wasi` npm package can be built locally
via `pnpm build` and then run with the Oxide API. A usage example can be
taken from the newly added integration test.
Furthermore this was tested to work as a polyfill on StackBlitz:
https://stackblitz.com/edit/vitejs-vite-uks3gt5p
[ci-all]
---------
Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
Closes#17621
Chrome as a pretty ugly rendering glitch when using a `skew-*` utility
in Tailwind 4: https://play.tailwindcss.com/HuiZtbrHOc
The was not an issue in v3 since transforms were set up in a different
way. Without the `var(…)` syntax, the difference boils down to this:
```css
.skew-v3 {
transform: rotate(0) skewX(-20deg);
}
.skew-v4 {
transform: rotateX(0) rotateY(0) rotateZ(0) skewX(-20deg);
}
```
It appears that using any of the single-dimension rotate functions will
cause the Chrome rendering to glitch.
After doing some digging, we found [that initially these `@property`s
were defined as type `<transform-function>` and later changed to
`*`](https://github.com/tailwindlabs/tailwindcss/issues/15144). With a
type of `*`, it makes sense that the initial value of these variables
can default to `initial` without any compromises, allowing us to default
to something like this now:
```css
.skew-new {
transform: skewX(-20deg);
}
```
Tested this change in the latest version of Chrome (135) and it does
make the rendering glitch in the initial issue disappear. By using the
`var(--tw-rotate-x,)` syntax we also ensure this works on older versions
of Safari (tested on Safari 15.5 and 16.4).
Note, however, that there are still glitches happening when you combine
rotate and skew in the latest version of Chrome or when you transition
the `skew(…)` variable. This also happens in plain CSS with no variables
though, so there isn't something we can do about this:
https://play.tailwindcss.com/g3FXPEJHpn
## Test plan
- Tested on latest Chrome, Firefox, and Safari as well as Safari 15.5
and 16.4.
<img width="564" alt="Screenshot 2025-04-09 at 18 01 51"
src="https://github.com/user-attachments/assets/2e0b1c96-7c4d-41a8-b3d0-0f6134a3e635"
/>
Fixes#17643.
This PR completely removes the `color-mix()` function for
`shadow-inherit`. This does mean intensity and alpha channel support has
been removed when using `shadow-inherit`[^1].
With intensity modifiers in #17398, all colors are wrapped in
`color-mix()`. However, it seems `inherit` does not work as a value in
`color-mix()` in Firefox or Chrome (don't have a means to test Safari).
[^1]: While writing this, I noticed other color utilities allow alpha
channel modifier syntax for `inherit` - do we want to look at removing
those too?
---------
Co-authored-by: Philipp Spiess <hello@philippspiess.com>
Fixes#17622.
Adds a specific handling case in `themeableValues()` in
`packages/tailwindcss/src/compat/apply-config-to-theme.ts`. It seems
like this has unique handling in v3 for an array value, whereby the
second value is treated as a `line-height`.
---------
Co-authored-by: Philipp Spiess <hello@philippspiess.com>
Fixes#17614.
Candidate parsing for variants only account for the root `@` if there no
hyphens. It seems like the current logic assumes if it *does* have a
hyphen, then it would be one of `@min` or `@max`. However, with:
```css
@theme {
--container-foo-bar: 1440px;
}
```
Then `@foo-bar` should be valid. However, we only check for `@foo-bar`
and `@foo` as roots, but never `@`. This PR adds a check for `@` at the
very end after iterating through root permutations.
---------
Co-authored-by: Philipp Spiess <hello@philippspiess.com>
Discovered while triaging #17556
This PR improves the `color-mix(...)` polyfill to ensure it works when a
theme key links to another theme key via a `var(...)` call.
Imagine this setup:
```css
@theme {
--color-red: var(--color-red-500);
--color-red-500: oklch(63.7% 0.237 25.331);
}
@source inline("text-red/50");
````
Since `--color-red` will link to `--color-red-500` _which is also a
known theme variable_, we can inline the value of `--color-red-500` into
the fallback now:
```css
.text-red\\/50 {
color: var(--color-red);
}
@supports (color: color-mix(in lab, red, red)) {
.text-red\\/50 {
color: color-mix(in oklab, var(--color-red) 50%, transparent);
}
}
```
This will allow for slightly less confusing behavior.
The code added also handles recursive definitions where a color is
linking to another color that is again linking to the first one (by
adding a `Set` to keep track of already seen variable names).
## Test plan
- Added unit test
This PR fixes an issue we noticed while investigating #17553, where the
unused CSS variable removal didn't work properly when the theme variable
it tried to remove was modified by a polyfill rule.
The way the bookkeeping for the unused CSS variable worked was that it
tired to find the declaration inside it's parent after the traversal.
However, the `color-mix(…)` polyfill has since then made changes to the
declaration so it can't find it's position correctly anymore and will
thus instead delete the last declaration of the node (this caused
unrelated CSS variables to be eliminated while the ones with
`color-mix(…)` were unexpectedly kept).
To fix this, we decided to apply the polyfills after any eventual
deletions. This also ensures that no `@supports` query for the variables
are created and simplifies the code a bit since all polyfills are now
colocated.
## Test plan
- Added a unit test for the example we discovered in #17553
- Luckily the conditions of this seemed rare enough so that it doesn't
cause any other of our tests to update.
---------
Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
This PR fixes an issue where the Ruby `%w[…]` syntax causes utilities to
not be properly extracted.
This PR will now ensure that it does get extracted correctly.
Given this input:
```slim
div[
class=%w[bg-blue-500 w-10 h-10]
]
div[
class=%w[w-10 bg-green-500 h-10]
]
```
Before this PR, we extracted everything but the `bg-blue-500`. The
`w-10` was extracted but not because of the second div, but because of
the first one.
Fixes: #17542
## Test plan
1. Added a test to ensure it's working correctly.
Looking at the extractor tool, you can see that it now gets extracted
correctly. Top is before, bottom is with this change.
<img width="1199" alt="image"
src="https://github.com/user-attachments/assets/028d9abd-8917-438c-a423-88ba887b7f97"
/>
Closes#17508
This PR fixes another issue we found that caused dev builds with Next.js
and Turbopack to resolve the CSS file that was saved one revision before
the latest update.
When debugging this we noticed that the PostCSS entry is called twice
for every one update when changing the input CSS file directly. That was
caused by the input file itself being added as a _dependency_ so you
would first get the callback that a _dependency_ has updated (at which
point we look at the file system and figure out we need a full-rebuild
because the input.css file has changed) and then another callback for
when the _input file_ has updated. The problem with the second callback
was that the file-system was already scanned for updates and since this
includes the `mtimes` for the input file, we seemingly thought that the
input file did not change. However, the issue is that the first callback
actually came with an outdated PostCSS input AST...
We found that this problem arises when you register the input CSS as a
dependency of itself. This is not expected and we actually guard against
this in the PostCSS client. However, we found that the input `from`
argument is _a relative path when using Next.js with Turbopack_ so that
check was not working as expected.
## Test plan
Added the change to the repro from #17508 and it seems to work fine now.
https://github.com/user-attachments/assets/2acb0078-f961-4498-be1a-b1c72d5ceda1
Also added a unit test to ensure we document that the input file path
can be a relative path.
Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
This PR will show a warning if you are using a bare value data type that
is not supported.
Let's say you want to create a new utility that allows `color` to be a
bare value data type like this:
```css
@utility paint-* {
paint: --value([color], color);
}
```
This means that this would enable new syntax that we don't support yet.
E.g.: `paint-#0088cc`.
The only supported data types for bare values are:
- `number` — `2.5`
- `integer` — `2`
- `ratio` — `1/2`
- `percentage` — `50%`
All other data types are not supported in this position. This PR will
now show a warning:
~~~
Unsupported bare value data type: "color".
Only valid data types are: "number", "integer", "ratio", "percentage".
```css
--value([color],color)
^^^^^
```
~~~
Once we have better sourcemap / location tracking support, this warning
will point to the exact spot, but for now, only a re-print of the AST
can be used.
If you _do_ want to use other data types, then you will have to use
arbitrary value syntax with `[…]` instead.
```css
@utility paint-* {
paint: --value([color]);
}
```
This will allow for `paint-[#0088cc]` for example.
Note: this is not a behavioral change, we already didn't support other
data types, but we silently ignored them. This means that we have to do
more parsing at runtime when evaluating the utility.
With this change, a warning is shown when registering the `@utility`,
not when using it.
Closes#17512
One of the changes of the Oxide API in 4.1 is that it now emits the
input CSS file itself as a dependency. This was fine in most of our
testing but it turns out that certain integrations (in this case a Qwik
project) don't like this and will silently crash with no CSS file being
added anymore.
This PR fixes this by making sure we don't add the input file as a
dependency on itself and also adds an integration test to ensure this
won't regress again.
## Test plan
- Tested with the repro provided in #17512
- Added a minimal integration test based on that reproduction that I
also validated will _fail_, if the fix is reverted.
This PR further improves the `color-mix(…)` polyfill to create a
reasonable fallback if dynamic values that can not statically be
resolved are used. This refers to either the use of `currentcolor` or
any variables that are not static theme variables.
Here are two examples that now generate a reasonable fallback instead of
not showing any color at all:
```css
.text-\\(--my-color\\)\\/\\(--my-opacity\\) {
color: var(--my-color);
}
@supports (color: color-mix(in lab, red, red)) {
.text-\\(--my-color\\)\\/\\(--my-opacity\\) {
color: color-mix(in oklab, var(--my-color) var(--my-opacity), transparent);
}
}
```
```css
.text-current\\/50 {
color: currentColor;
}
@supports (color: color-mix(in lab, red, red)) {
.text-current\\/50 {
color: color-mix(in oklab, currentColor 50%, transparent);
}
}
```
## Test plan
- Made sure the test diffs are looking reasonable
- Tested this on a production site with `<p className="text-shadow-lg/50
[--my-color:red] text-shadow-(color:--my-color)">shadow test</p>`
- Browsers that do not support `color-mix(…)` will properly show a red
shadow now albeit with 100% opacity: iOS 15.5 and Chrome 110
- Browsers that I have tested to make sure it still works there with
opacity: Firefox 127, Firefox 128, Latest Chrome, Safari, Firefox
- Browsers that do show a black shadow because of `var(…)var(…)` being
chained with no space by lightningcss: Chrome 111
This PR fixes an issue where if you use Next.js with `--turbopack` a
race condition happens because the `@tailwindcss/postcss` plugin is
called twice in rapid succession.
The first call sees an update and does a partial update with the new
classes. Next some internal `mtimes` are updated. The second call
therefore doesn't see any changes anymore because the `mtimes` are the
same, therefore it's serving its stale data.
Fixes: #17508
## Test plan
- Tested with the repro provided in #17508
- Added a new unit test that calls into the PostCSS plugin directly for
the same change from the same JavaScript run-loop.
---------
Co-authored-by: Philipp Spiess <hello@philippspiess.com>
It seems that I broke support for multiple drop-shadow filters when
`@theme inline` was used in v4.1. This PR fixes that by segmenting the
drop shadow value on top-level commas and wrapping each segment with
`drop-shadow(…)` like we did in v4.0.