154 Commits

Author SHA1 Message Date
Philipp Spiess
85d7375b59
Prepare v4.0.9 release (#16804)
Co-authored-by: Adam Wathan <adam.wathan@gmail.com>
2025-02-25 17:33:28 +01:00
Philipp Spiess
b38948337d
Make @reference emit variable fallbacks instead of CSS variable declarations (#16774)
Fixes #16725

When using `@reference "tailwindcss";` inside a separate CSS root (e.g.
Svelte `<style>` components, CSS modules, etc.), we have no guarantee
that the CSS variables will be defined in the main stylesheet (or if
there even is one). To work around potential issues with this we decided
in #16676 that we would emit all used CSS variables from the `@theme`
inside the `@reference` block.

However, this is not only a bit surprising but also unexpected in CSS
modules and Next.js that **requires CSS module files to only create
scope-able declarations**. To fix this issue, we decided to not emit CSS
variables but instead ensure all `var(…)` calls we create for theme
values in reference mode will simply have their fallback value added.

This ensures styles work as-expected even if the root Tailwind file does
not pick up the variable as being used or _if you don't add a root at
all_. Furthermore we do not duplicate any variable declarations across
your stylesheets and you still have the ability to change variables at
runtime.

## Test plan

- Updated snapshots everywhere (see diff)
- New Next.js CSS modules integration test
2025-02-25 11:36:43 +01:00
Philipp Spiess
419b3dc473
Prepare v4.0.8 release (#16713)
<!--

👋 Hey, thanks for your interest in contributing to Tailwind!

**Please ask first before starting work on any significant new
features.**

It's never a fun experience to have your pull request declined after
investing a lot of time and effort into a new feature. To avoid this
from happening, we request that contributors create an issue to first
discuss any significant new features. This includes things like adding
new utilities, creating new at-rules, or adding new component examples
to the documentation.


https://github.com/tailwindcss/tailwindcss/blob/master/.github/CONTRIBUTING.md

-->

---------

Co-authored-by: Adam Wathan <adam.wathan@gmail.com>
2025-02-21 16:06:37 +01:00
Philipp Spiess
7bece4de7c
Re-enable: Only expose used CSS variables (#16676)
This PR re-enables the changes necessary to remove unused theme
variables and keyframes form your CSS.

This change was initially landed as #16211 and then later reverted in
#16403 because we found some unexpected interactions with using `@apply`
and CSS variables in multi-root setups like CSS modules or Vue inline
`<style>` blocks that were no longer seeing their required variables
defined.

This issue is fixed by now ensuring that theme variables that are
defined within an `@reference "…"` boundary will still be emitted in the
generated CSS when used (as this would otherwise not generate a valid
stylesheet).

So given the following input CSS:

```css
@reference "tailwindcss";
.text-red {
  @apply text-red-500;
}
```

We will now compile this to:

```css
@layer theme {
  :root, :host {
    --text-red-500: oklch(0.637 0.237 25.331);
  }
}
.text-red {
  color: var(--text-red-500);
}
```

This PR also improves the initial implementation to not mark theme
variables as used if they are only used to define other theme variables.
For example:

```css
@theme {
  --font-sans:
    ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol',
    'Noto Color Emoji';
  --font-mono:
    ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New',
    monospace;

  --default-font-family: var(--font-sans);
  --default-mono-font-family: var(--font-mono);
}

.default-font-family {
  font-family: var(--default-font-family);
}
```

This would be reduced to the following now as `--font-mono` is only used
to define another variable and never used outside the theme block:

```css
:root, :host {
  --font-sans:
    ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol',
    'Noto Color Emoji';
  --default-font-family: var(--font-sans);
}

.default-font-family {
  font-family: var(--default-font-family);
}
```

## Test plan

- See updated unit and integration tests
- Validated it works end-to-end by using a SvelteKit example
2025-02-21 10:45:22 +01:00
Philipp Spiess
541c3d2331
Prepare v4.0.7 release (#16629)
Co-authored-by: Adam Wathan <adam.wathan@gmail.com>
2025-02-18 16:51:20 +01:00
Robin Malfait
f0141084c2
Pin exact versions of tailwindcss and @tailwindcss/* (#16623)
This PR fixes an issue where installing a specific version of
`@tailwindcss/postcss` and `tailwindcss` could still result in a version
mismatch. This is because we were relying on `^4.0.6` for example
instead of `4.0.6`.

This PR now pins all these versions to prevent this:
```
❯ pnpm why tailwindcss
devDependencies:
@tailwindcss/postcss 4.0.5
├─┬ @tailwindcss/node 4.0.6
│ └── tailwindcss 4.0.6
└── tailwindcss 4.0.5
```
2025-02-18 11:44:12 +01:00
Robin Malfait
d045aaa75e
Prepare v4.0.6 (#16407) 2025-02-10 14:09:00 +01:00
Philipp Spiess
9bbe2e3d08
Revert: Only expose used CSS variables (#16403)
This reverts #16211

We found some unexpected interactions with using `@apply` and CSS
variables in multi-root setups like CSS modules or Vue inline `<style>`
blocks that were broken due to that change. We plan to re-enable this
soon and include a proper fix for those scenarios.

## Test plan

- Updated snapshots
- Tested using the CLI in a new project:
<img width="1523" alt="Screenshot 2025-02-10 at 13 08 42"
src="https://github.com/user-attachments/assets/defe0858-adb3-4d61-9d2c-87166558fd68"
/>

---------

Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
2025-02-10 13:26:13 +01:00
Adam Wathan
ad001199f6
Prepare v4.0.5 (#16373)
<!--

👋 Hey, thanks for your interest in contributing to Tailwind!

**Please ask first before starting work on any significant new
features.**

It's never a fun experience to have your pull request declined after
investing a lot of time and effort into a new feature. To avoid this
from happening, we request that contributors create an issue to first
discuss any significant new features. This includes things like adding
new utilities, creating new at-rules, or adding new component examples
to the documentation.


https://github.com/tailwindcss/tailwindcss/blob/master/.github/CONTRIBUTING.md

-->

---------

Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2025-02-08 13:48:34 -05:00
Robin Malfait
d684733d80
Only expose used CSS variables (#16211)
This PR only exposes used CSS variables. 

My initial approach was to track the used variables, this was a bit
messy because it meant that we had to walk part of the AST(s) in
multiple places. We also had to be careful because sometimes if a
variable exists in an AST, that doesn't mean that it's actually used.
E.g.:

```css
h1 {
  color: var(--color-red-500); /* Definitely used, so let's keep it */
}

@utility foo {
  color: var(--color-blue-500); /* Hmm, used? */
}
```
In this last case, the `--color-blue-500` is part of the CSS AST, but as
long as `foo` the utility is not used, it won't end up in your actual
CSS file, therefore the variable is **not** used.

Alternatively, if the `foo` utility is used with an invalid variant
(e.g.: `group-[>.foo]:foo`, then the `@utility foo` code will still run
internally because variants are applied on top of the utility. This
means that it looks like `var(--color-blue-500)` is being used.

Another annoying side effect was that because variables are
conditionally generated, that the `@theme` -> `:root, :host` conversion
had to happen for every build, instead of once in the `compile(…)` step.

---

To prevent all the messy rules and additional booking while walking of
ASTs I thought about a different approach. We are only interested in
variables that are actually used. The only way we know for sure, is
right before the `toCss(…)` step. Any step before that could still throw
away AST nodes.

However, we do have an `optimizeAst` step right before printing to
simplify and optimize the AST. So the idea was to keep all the CSS
variables in the AST, and only in the `optimizeAst` step we perform a
kind of mark-and-sweep algorithm where we can first check which
variables are _actually_ used (these are the ones that are left in the
AST), and later we removed the ones that weren't part of known used
list.

Moving the logic to this step feels a natural spot for this to happen,
because we are in fact optimizing the AST. We were already walking the
AST, so we can just handle these cases while we are walking without
additional walks. Last but not least, this also means that there is only
a single spot where need to track and remove variables.

Now, there is a different part to this story. If you use a variable in
JS land for example, we also want to make sure that we keep the CSS
variable in the CSS. To do this, we can mark variables as being used in
the internal `Theme`.

The Oxide scanner will also emit used variables that it can find such as
`var(--color-red-500)` and will emit `--color-red-500` as a "candidate".
We can then proactively mark this one as used even though it may not be
used anyway in the actual AST.

---

### Always including all variables

Some users might make heavy use of JavaScript and string interpolation
where they _need_ all the variables to be present. Similar to the
`inline` and `reference` theme options, this also exposes a new `static`
option. This ensures that all the CSS variables will always be generated
regardless of whether it's used or not.

One handy feature is that you have granular control over this:
```css
/* These will always be generated */
@theme static {
  --color-primary: red;
  --color-secondary: blue;
}

/* Only generated when used */
@theme {
  --color-maybe: pink;
}
```

### Performance considerations:

Now that we are tracking which variables are being used, it means that
we will produce a smaller CSS file, but we are also doing more work (the
mark-and-sweep part). That said, ran some benchmarks and the changes
look like this:

Running it on Catalyst:
<img width="1086" alt="image"
src="https://github.com/user-attachments/assets/ec2124f0-2e64-4a11-aa5e-5f7ae6605962"
/>
_(probably within margin of error)_

Running it on Tailwind UI:
<img width="1113" alt="image"
src="https://github.com/user-attachments/assets/6bea2328-d790-4f33-a0ae-72654c688edb"
/>

### Test plan

- Tests have been updated with the removed CSS variables
- Added a dedicated integration test to show that Oxide can find
variables and mark them as used (so they are included)
- Ran the code on Catalyst, and verified that all the removed variables
are in fact not used anywhere in the codebase.

The diff on Catalyst looks like this:

<details>

```diff
diff --git a/templates/catalyst/out.css b/templates/catalyst/out.css
index f2b364ea..240d1d90 100644
--- a/templates/catalyst/out.css
+++ b/templates/catalyst/out.css
@@ -29,218 +29,111 @@
 @layer theme {
   :root, :host {
     --font-sans: Inter, sans-serif;
-    --font-serif: ui-serif, Georgia, Cambria, "Times New Roman", Times, serif;
     --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
       "Liberation Mono", "Courier New", monospace;
-    --color-red-50: oklch(0.971 0.013 17.38);
-    --color-red-100: oklch(0.936 0.032 17.717);
     --color-red-200: oklch(0.885 0.062 18.334);
     --color-red-300: oklch(0.808 0.114 19.571);
     --color-red-400: oklch(0.704 0.191 22.216);
     --color-red-500: oklch(0.637 0.237 25.331);
     --color-red-600: oklch(0.577 0.245 27.325);
     --color-red-700: oklch(0.505 0.213 27.518);
-    --color-red-800: oklch(0.444 0.177 26.899);
     --color-red-900: oklch(0.396 0.141 25.723);
-    --color-red-950: oklch(0.258 0.092 26.042);
-    --color-orange-50: oklch(0.98 0.016 73.684);
-    --color-orange-100: oklch(0.954 0.038 75.164);
     --color-orange-200: oklch(0.901 0.076 70.697);
     --color-orange-300: oklch(0.837 0.128 66.29);
     --color-orange-400: oklch(0.75 0.183 55.934);
     --color-orange-500: oklch(0.705 0.213 47.604);
     --color-orange-600: oklch(0.646 0.222 41.116);
     --color-orange-700: oklch(0.553 0.195 38.402);
-    --color-orange-800: oklch(0.47 0.157 37.304);
     --color-orange-900: oklch(0.408 0.123 38.172);
-    --color-orange-950: oklch(0.266 0.079 36.259);
-    --color-amber-50: oklch(0.987 0.022 95.277);
-    --color-amber-100: oklch(0.962 0.059 95.617);
-    --color-amber-200: oklch(0.924 0.12 95.746);
-    --color-amber-300: oklch(0.879 0.169 91.605);
     --color-amber-400: oklch(0.828 0.189 84.429);
     --color-amber-500: oklch(0.769 0.188 70.08);
     --color-amber-600: oklch(0.666 0.179 58.318);
     --color-amber-700: oklch(0.555 0.163 48.998);
-    --color-amber-800: oklch(0.473 0.137 46.201);
-    --color-amber-900: oklch(0.414 0.112 45.904);
     --color-amber-950: oklch(0.279 0.077 45.635);
-    --color-yellow-50: oklch(0.987 0.026 102.212);
-    --color-yellow-100: oklch(0.973 0.071 103.193);
-    --color-yellow-200: oklch(0.945 0.129 101.54);
     --color-yellow-300: oklch(0.905 0.182 98.111);
     --color-yellow-400: oklch(0.852 0.199 91.936);
-    --color-yellow-500: oklch(0.795 0.184 86.047);
     --color-yellow-600: oklch(0.681 0.162 75.834);
     --color-yellow-700: oklch(0.554 0.135 66.442);
-    --color-yellow-800: oklch(0.476 0.114 61.907);
-    --color-yellow-900: oklch(0.421 0.095 57.708);
     --color-yellow-950: oklch(0.286 0.066 53.813);
-    --color-lime-50: oklch(0.986 0.031 120.757);
-    --color-lime-100: oklch(0.967 0.067 122.328);
-    --color-lime-200: oklch(0.938 0.127 124.321);
     --color-lime-300: oklch(0.897 0.196 126.665);
     --color-lime-400: oklch(0.841 0.238 128.85);
-    --color-lime-500: oklch(0.768 0.233 130.85);
     --color-lime-600: oklch(0.648 0.2 131.684);
     --color-lime-700: oklch(0.532 0.157 131.589);
-    --color-lime-800: oklch(0.453 0.124 130.933);
-    --color-lime-900: oklch(0.405 0.101 131.063);
     --color-lime-950: oklch(0.274 0.072 132.109);
-    --color-green-50: oklch(0.982 0.018 155.826);
-    --color-green-100: oklch(0.962 0.044 156.743);
-    --color-green-200: oklch(0.925 0.084 155.995);
-    --color-green-300: oklch(0.871 0.15 154.449);
     --color-green-400: oklch(0.792 0.209 151.711);
     --color-green-500: oklch(0.723 0.219 149.579);
     --color-green-600: oklch(0.627 0.194 149.214);
     --color-green-700: oklch(0.527 0.154 150.069);
-    --color-green-800: oklch(0.448 0.119 151.328);
     --color-green-900: oklch(0.393 0.095 152.535);
-    --color-green-950: oklch(0.266 0.065 152.934);
-    --color-emerald-50: oklch(0.979 0.021 166.113);
-    --color-emerald-100: oklch(0.95 0.052 163.051);
-    --color-emerald-200: oklch(0.905 0.093 164.15);
-    --color-emerald-300: oklch(0.845 0.143 164.978);
     --color-emerald-400: oklch(0.765 0.177 163.223);
     --color-emerald-500: oklch(0.696 0.17 162.48);
     --color-emerald-600: oklch(0.596 0.145 163.225);
     --color-emerald-700: oklch(0.508 0.118 165.612);
-    --color-emerald-800: oklch(0.432 0.095 166.913);
     --color-emerald-900: oklch(0.378 0.077 168.94);
-    --color-emerald-950: oklch(0.262 0.051 172.552);
-    --color-teal-50: oklch(0.984 0.014 180.72);
-    --color-teal-100: oklch(0.953 0.051 180.801);
-    --color-teal-200: oklch(0.91 0.096 180.426);
     --color-teal-300: oklch(0.855 0.138 181.071);
     --color-teal-400: oklch(0.777 0.152 181.912);
     --color-teal-500: oklch(0.704 0.14 182.503);
     --color-teal-600: oklch(0.6 0.118 184.704);
     --color-teal-700: oklch(0.511 0.096 186.391);
-    --color-teal-800: oklch(0.437 0.078 188.216);
     --color-teal-900: oklch(0.386 0.063 188.416);
-    --color-teal-950: oklch(0.277 0.046 192.524);
-    --color-cyan-50: oklch(0.984 0.019 200.873);
-    --color-cyan-100: oklch(0.956 0.045 203.388);
-    --color-cyan-200: oklch(0.917 0.08 205.041);
     --color-cyan-300: oklch(0.865 0.127 207.078);
     --color-cyan-400: oklch(0.789 0.154 211.53);
     --color-cyan-500: oklch(0.715 0.143 215.221);
-    --color-cyan-600: oklch(0.609 0.126 221.723);
     --color-cyan-700: oklch(0.52 0.105 223.128);
-    --color-cyan-800: oklch(0.45 0.085 224.283);
-    --color-cyan-900: oklch(0.398 0.07 227.392);
     --color-cyan-950: oklch(0.302 0.056 229.695);
-    --color-sky-50: oklch(0.977 0.013 236.62);
-    --color-sky-100: oklch(0.951 0.026 236.824);
-    --color-sky-200: oklch(0.901 0.058 230.902);
     --color-sky-300: oklch(0.828 0.111 230.318);
-    --color-sky-400: oklch(0.746 0.16 232.661);
     --color-sky-500: oklch(0.685 0.169 237.323);
     --color-sky-600: oklch(0.588 0.158 241.966);
     --color-sky-700: oklch(0.5 0.134 242.749);
-    --color-sky-800: oklch(0.443 0.11 240.79);
     --color-sky-900: oklch(0.391 0.09 240.876);
-    --color-sky-950: oklch(0.293 0.066 243.157);
-    --color-blue-50: oklch(0.97 0.014 254.604);
-    --color-blue-100: oklch(0.932 0.032 255.585);
-    --color-blue-200: oklch(0.882 0.059 254.128);
     --color-blue-300: oklch(0.809 0.105 251.813);
     --color-blue-400: oklch(0.707 0.165 254.624);
     --color-blue-500: oklch(0.623 0.214 259.815);
     --color-blue-600: oklch(0.546 0.245 262.881);
     --color-blue-700: oklch(0.488 0.243 264.376);
-    --color-blue-800: oklch(0.424 0.199 265.638);
     --color-blue-900: oklch(0.379 0.146 265.522);
-    --color-blue-950: oklch(0.282 0.091 267.935);
-    --color-indigo-50: oklch(0.962 0.018 272.314);
-    --color-indigo-100: oklch(0.93 0.034 272.788);
     --color-indigo-200: oklch(0.87 0.065 274.039);
     --color-indigo-300: oklch(0.785 0.115 274.713);
     --color-indigo-400: oklch(0.673 0.182 276.935);
     --color-indigo-500: oklch(0.585 0.233 277.117);
     --color-indigo-600: oklch(0.511 0.262 276.966);
     --color-indigo-700: oklch(0.457 0.24 277.023);
-    --color-indigo-800: oklch(0.398 0.195 277.366);
     --color-indigo-900: oklch(0.359 0.144 278.697);
-    --color-indigo-950: oklch(0.257 0.09 281.288);
-    --color-violet-50: oklch(0.969 0.016 293.756);
-    --color-violet-100: oklch(0.943 0.029 294.588);
     --color-violet-200: oklch(0.894 0.057 293.283);
     --color-violet-300: oklch(0.811 0.111 293.571);
     --color-violet-400: oklch(0.702 0.183 293.541);
     --color-violet-500: oklch(0.606 0.25 292.717);
     --color-violet-600: oklch(0.541 0.281 293.009);
     --color-violet-700: oklch(0.491 0.27 292.581);
-    --color-violet-800: oklch(0.432 0.232 292.759);
     --color-violet-900: oklch(0.38 0.189 293.745);
-    --color-violet-950: oklch(0.283 0.141 291.089);
-    --color-purple-50: oklch(0.977 0.014 308.299);
-    --color-purple-100: oklch(0.946 0.033 307.174);
     --color-purple-200: oklch(0.902 0.063 306.703);
     --color-purple-300: oklch(0.827 0.119 306.383);
     --color-purple-400: oklch(0.714 0.203 305.504);
     --color-purple-500: oklch(0.627 0.265 303.9);
     --color-purple-600: oklch(0.558 0.288 302.321);
     --color-purple-700: oklch(0.496 0.265 301.924);
-    --color-purple-800: oklch(0.438 0.218 303.724);
     --color-purple-900: oklch(0.381 0.176 304.987);
-    --color-purple-950: oklch(0.291 0.149 302.717);
-    --color-fuchsia-50: oklch(0.977 0.017 320.058);
-    --color-fuchsia-100: oklch(0.952 0.037 318.852);
     --color-fuchsia-200: oklch(0.903 0.076 319.62);
     --color-fuchsia-300: oklch(0.833 0.145 321.434);
     --color-fuchsia-400: oklch(0.74 0.238 322.16);
     --color-fuchsia-500: oklch(0.667 0.295 322.15);
     --color-fuchsia-600: oklch(0.591 0.293 322.896);
     --color-fuchsia-700: oklch(0.518 0.253 323.949);
-    --color-fuchsia-800: oklch(0.452 0.211 324.591);
     --color-fuchsia-900: oklch(0.401 0.17 325.612);
-    --color-fuchsia-950: oklch(0.293 0.136 325.661);
-    --color-pink-50: oklch(0.971 0.014 343.198);
-    --color-pink-100: oklch(0.948 0.028 342.258);
     --color-pink-200: oklch(0.899 0.061 343.231);
     --color-pink-300: oklch(0.823 0.12 346.018);
     --color-pink-400: oklch(0.718 0.202 349.761);
     --color-pink-500: oklch(0.656 0.241 354.308);
     --color-pink-600: oklch(0.592 0.249 0.584);
     --color-pink-700: oklch(0.525 0.223 3.958);
-    --color-pink-800: oklch(0.459 0.187 3.815);
     --color-pink-900: oklch(0.408 0.153 2.432);
-    --color-pink-950: oklch(0.284 0.109 3.907);
-    --color-rose-50: oklch(0.969 0.015 12.422);
-    --color-rose-100: oklch(0.941 0.03 12.58);
     --color-rose-200: oklch(0.892 0.058 10.001);
     --color-rose-300: oklch(0.81 0.117 11.638);
     --color-rose-400: oklch(0.712 0.194 13.428);
     --color-rose-500: oklch(0.645 0.246 16.439);
     --color-rose-600: oklch(0.586 0.253 17.585);
     --color-rose-700: oklch(0.514 0.222 16.935);
-    --color-rose-800: oklch(0.455 0.188 13.697);
     --color-rose-900: oklch(0.41 0.159 10.272);
-    --color-rose-950: oklch(0.271 0.105 12.094);
-    --color-slate-50: oklch(0.984 0.003 247.858);
-    --color-slate-100: oklch(0.968 0.007 247.896);
-    --color-slate-200: oklch(0.929 0.013 255.508);
-    --color-slate-300: oklch(0.869 0.022 252.894);
-    --color-slate-400: oklch(0.704 0.04 256.788);
-    --color-slate-500: oklch(0.554 0.046 257.417);
-    --color-slate-600: oklch(0.446 0.043 257.281);
-    --color-slate-700: oklch(0.372 0.044 257.287);
-    --color-slate-800: oklch(0.279 0.041 260.031);
-    --color-slate-900: oklch(0.208 0.042 265.755);
-    --color-slate-950: oklch(0.129 0.042 264.695);
-    --color-gray-50: oklch(0.985 0.002 247.839);
-    --color-gray-100: oklch(0.967 0.003 264.542);
-    --color-gray-200: oklch(0.928 0.006 264.531);
-    --color-gray-300: oklch(0.872 0.01 258.338);
-    --color-gray-400: oklch(0.707 0.022 261.325);
-    --color-gray-500: oklch(0.551 0.027 264.364);
-    --color-gray-600: oklch(0.446 0.03 256.802);
-    --color-gray-700: oklch(0.373 0.034 259.733);
-    --color-gray-800: oklch(0.278 0.033 256.848);
-    --color-gray-900: oklch(0.21 0.034 264.665);
-    --color-gray-950: oklch(0.13 0.028 261.692);
     --color-zinc-50: oklch(0.985 0 0);
     --color-zinc-100: oklch(0.967 0.001 286.375);
     --color-zinc-200: oklch(0.92 0.004 286.32);
@@ -252,38 +145,9 @@
     --color-zinc-800: oklch(0.274 0.006 286.033);
     --color-zinc-900: oklch(0.21 0.006 285.885);
     --color-zinc-950: oklch(0.141 0.005 285.823);
-    --color-neutral-50: oklch(0.985 0 0);
-    --color-neutral-100: oklch(0.97 0 0);
-    --color-neutral-200: oklch(0.922 0 0);
-    --color-neutral-300: oklch(0.87 0 0);
-    --color-neutral-400: oklch(0.708 0 0);
-    --color-neutral-500: oklch(0.556 0 0);
-    --color-neutral-600: oklch(0.439 0 0);
-    --color-neutral-700: oklch(0.371 0 0);
-    --color-neutral-800: oklch(0.269 0 0);
-    --color-neutral-900: oklch(0.205 0 0);
-    --color-neutral-950: oklch(0.145 0 0);
-    --color-stone-50: oklch(0.985 0.001 106.423);
-    --color-stone-100: oklch(0.97 0.001 106.424);
-    --color-stone-200: oklch(0.923 0.003 48.717);
-    --color-stone-300: oklch(0.869 0.005 56.366);
-    --color-stone-400: oklch(0.709 0.01 56.259);
-    --color-stone-500: oklch(0.553 0.013 58.071);
-    --color-stone-600: oklch(0.444 0.011 73.639);
-    --color-stone-700: oklch(0.374 0.01 67.558);
-    --color-stone-800: oklch(0.268 0.007 34.298);
-    --color-stone-900: oklch(0.216 0.006 56.043);
-    --color-stone-950: oklch(0.147 0.004 49.25);
     --color-black: #000;
     --color-white: #fff;
     --spacing: 0.25rem;
-    --breakpoint-sm: 40rem;
-    --breakpoint-md: 48rem;
-    --breakpoint-lg: 64rem;
-    --breakpoint-xl: 80rem;
-    --breakpoint-2xl: 96rem;
-    --container-3xs: 16rem;
-    --container-2xs: 18rem;
     --container-xs: 20rem;
     --container-sm: 24rem;
     --container-md: 28rem;
@@ -302,92 +166,23 @@
     --text-base: 1rem;
     --text-base--line-height: calc(1.5 / 1);
     --text-lg: 1.125rem;
-    --text-lg--line-height: calc(1.75 / 1.125);
     --text-xl: 1.25rem;
-    --text-xl--line-height: calc(1.75 / 1.25);
     --text-2xl: 1.5rem;
-    --text-2xl--line-height: calc(2 / 1.5);
-    --text-3xl: 1.875rem;
-    --text-3xl--line-height: calc(2.25 / 1.875);
-    --text-4xl: 2.25rem;
-    --text-4xl--line-height: calc(2.5 / 2.25);
-    --text-5xl: 3rem;
-    --text-5xl--line-height: 1;
-    --text-6xl: 3.75rem;
-    --text-6xl--line-height: 1;
-    --text-7xl: 4.5rem;
-    --text-7xl--line-height: 1;
-    --text-8xl: 6rem;
-    --text-8xl--line-height: 1;
-    --text-9xl: 8rem;
-    --text-9xl--line-height: 1;
-    --font-weight-thin: 100;
-    --font-weight-extralight: 200;
-    --font-weight-light: 300;
     --font-weight-normal: 400;
     --font-weight-medium: 500;
     --font-weight-semibold: 600;
     --font-weight-bold: 700;
-    --font-weight-extrabold: 800;
-    --font-weight-black: 900;
-    --tracking-tighter: -0.05em;
-    --tracking-tight: -0.025em;
-    --tracking-normal: 0em;
-    --tracking-wide: 0.025em;
-    --tracking-wider: 0.05em;
-    --tracking-widest: 0.1em;
-    --leading-tight: 1.25;
-    --leading-snug: 1.375;
-    --leading-normal: 1.5;
-    --leading-relaxed: 1.625;
-    --leading-loose: 2;
-    --radius-xs: 0.125rem;
     --radius-sm: 0.25rem;
     --radius-md: 0.375rem;
     --radius-lg: 0.5rem;
     --radius-xl: 0.75rem;
     --radius-2xl: 1rem;
     --radius-3xl: 1.5rem;
-    --radius-4xl: 2rem;
-    --shadow-2xs: 0 1px rgb(0 0 0 / 0.05);
-    --shadow-xs: 0 1px 2px 0 rgb(0 0 0 / 0.05);
-    --shadow-sm: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
-    --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1),
-      0 2px 4px -2px rgb(0 0 0 / 0.1);
-    --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1),
-      0 4px 6px -4px rgb(0 0 0 / 0.1);
-    --shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1),
-      0 8px 10px -6px rgb(0 0 0 / 0.1);
-    --shadow-2xl: 0 25px 50px -12px rgb(0 0 0 / 0.25);
-    --inset-shadow-2xs: inset 0 1px rgb(0 0 0 / 0.05);
-    --inset-shadow-xs: inset 0 1px 1px rgb(0 0 0 / 0.05);
-    --inset-shadow-sm: inset 0 2px 4px rgb(0 0 0 / 0.05);
-    --drop-shadow-xs: 0 1px 1px rgb(0 0 0 / 0.05);
-    --drop-shadow-sm: 0 1px 2px rgb(0 0 0 / 0.15);
-    --drop-shadow-md: 0 3px 3px rgb(0 0 0 / 0.12);
-    --drop-shadow-lg: 0 4px 4px rgb(0 0 0 / 0.15);
-    --drop-shadow-xl: 0 9px 7px rgb(0 0 0 / 0.1);
-    --drop-shadow-2xl: 0 25px 25px rgb(0 0 0 / 0.15);
     --ease-in: cubic-bezier(0.4, 0, 1, 1);
     --ease-out: cubic-bezier(0, 0, 0.2, 1);
     --ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
-    --animate-spin: spin 1s linear infinite;
-    --animate-ping: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite;
-    --animate-pulse: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
-    --animate-bounce: bounce 1s infinite;
-    --blur-xs: 4px;
-    --blur-sm: 8px;
     --blur-md: 12px;
-    --blur-lg: 16px;
     --blur-xl: 24px;
-    --blur-2xl: 40px;
-    --blur-3xl: 64px;
-    --perspective-dramatic: 100px;
-    --perspective-near: 300px;
-    --perspective-normal: 500px;
-    --perspective-midrange: 800px;
-    --perspective-distant: 1200px;
-    --aspect-video: 16 / 9;
     --default-transition-duration: 150ms;
     --default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
     --default-font-family: var(--font-sans);
```

</details>

If you have `ripgrep` installed, you can use this command to verify that
these variables are indeed not used anywhere:

<details>

```shell
rg "\-\-font-serif\b"
rg "\-\-color-red-50\b"
rg "\-\-color-red-100\b"
rg "\-\-color-red-800\b"
rg "\-\-color-red-950\b"
rg "\-\-color-orange-50\b"
rg "\-\-color-orange-100\b"
rg "\-\-color-orange-800\b"
rg "\-\-color-orange-950\b"
rg "\-\-color-amber-50\b"
rg "\-\-color-amber-100\b"
rg "\-\-color-amber-200\b"
rg "\-\-color-amber-300\b"
rg "\-\-color-amber-800\b"
rg "\-\-color-amber-900\b"
rg "\-\-color-yellow-50\b"
rg "\-\-color-yellow-100\b"
rg "\-\-color-yellow-200\b"
rg "\-\-color-yellow-500\b"
rg "\-\-color-yellow-800\b"
rg "\-\-color-yellow-900\b"
rg "\-\-color-lime-50\b"
rg "\-\-color-lime-100\b"
rg "\-\-color-lime-200\b"
rg "\-\-color-lime-500\b"
rg "\-\-color-lime-800\b"
rg "\-\-color-lime-900\b"
rg "\-\-color-green-50\b"
rg "\-\-color-green-100\b"
rg "\-\-color-green-200\b"
rg "\-\-color-green-300\b"
rg "\-\-color-green-800\b"
rg "\-\-color-green-950\b"
rg "\-\-color-emerald-50\b"
rg "\-\-color-emerald-100\b"
rg "\-\-color-emerald-200\b"
rg "\-\-color-emerald-300\b"
rg "\-\-color-emerald-800\b"
rg "\-\-color-emerald-950\b"
rg "\-\-color-teal-50\b"
rg "\-\-color-teal-100\b"
rg "\-\-color-teal-200\b"
rg "\-\-color-teal-800\b"
rg "\-\-color-teal-950\b"
rg "\-\-color-cyan-50\b"
rg "\-\-color-cyan-100\b"
rg "\-\-color-cyan-200\b"
rg "\-\-color-cyan-600\b"
rg "\-\-color-cyan-800\b"
rg "\-\-color-cyan-900\b"
rg "\-\-color-sky-50\b"
rg "\-\-color-sky-100\b"
rg "\-\-color-sky-200\b"
rg "\-\-color-sky-400\b"
rg "\-\-color-sky-800\b"
rg "\-\-color-sky-950\b"
rg "\-\-color-blue-50\b"
rg "\-\-color-blue-100\b"
rg "\-\-color-blue-200\b"
rg "\-\-color-blue-800\b"
rg "\-\-color-blue-950\b"
rg "\-\-color-indigo-50\b"
rg "\-\-color-indigo-100\b"
rg "\-\-color-indigo-800\b"
rg "\-\-color-indigo-950\b"
rg "\-\-color-violet-50\b"
rg "\-\-color-violet-100\b"
rg "\-\-color-violet-800\b"
rg "\-\-color-violet-950\b"
rg "\-\-color-purple-50\b"
rg "\-\-color-purple-100\b"
rg "\-\-color-purple-800\b"
rg "\-\-color-purple-950\b"
rg "\-\-color-fuchsia-50\b"
rg "\-\-color-fuchsia-100\b"
rg "\-\-color-fuchsia-800\b"
rg "\-\-color-fuchsia-950\b"
rg "\-\-color-pink-50\b"
rg "\-\-color-pink-100\b"
rg "\-\-color-pink-800\b"
rg "\-\-color-pink-950\b"
rg "\-\-color-rose-50\b"
rg "\-\-color-rose-100\b"
rg "\-\-color-rose-800\b"
rg "\-\-color-rose-950\b"
rg "\-\-color-slate-50\b"
rg "\-\-color-slate-100\b"
rg "\-\-color-slate-200\b"
rg "\-\-color-slate-300\b"
rg "\-\-color-slate-400\b"
rg "\-\-color-slate-500\b"
rg "\-\-color-slate-600\b"
rg "\-\-color-slate-700\b"
rg "\-\-color-slate-800\b"
rg "\-\-color-slate-900\b"
rg "\-\-color-slate-950\b"
rg "\-\-color-gray-50\b"
rg "\-\-color-gray-100\b"
rg "\-\-color-gray-200\b"
rg "\-\-color-gray-300\b"
rg "\-\-color-gray-400\b"
rg "\-\-color-gray-500\b"
rg "\-\-color-gray-600\b"
rg "\-\-color-gray-700\b"
rg "\-\-color-gray-800\b"
rg "\-\-color-gray-900\b"
rg "\-\-color-gray-950\b"
rg "\-\-color-neutral-50\b"
rg "\-\-color-neutral-100\b"
rg "\-\-color-neutral-200\b"
rg "\-\-color-neutral-300\b"
rg "\-\-color-neutral-400\b"
rg "\-\-color-neutral-500\b"
rg "\-\-color-neutral-600\b"
rg "\-\-color-neutral-700\b"
rg "\-\-color-neutral-800\b"
rg "\-\-color-neutral-900\b"
rg "\-\-color-neutral-950\b"
rg "\-\-color-stone-50\b"
rg "\-\-color-stone-100\b"
rg "\-\-color-stone-200\b"
rg "\-\-color-stone-300\b"
rg "\-\-color-stone-400\b"
rg "\-\-color-stone-500\b"
rg "\-\-color-stone-600\b"
rg "\-\-color-stone-700\b"
rg "\-\-color-stone-800\b"
rg "\-\-color-stone-900\b"
rg "\-\-color-stone-950\b"
rg "\-\-breakpoint-sm\b"
rg "\-\-breakpoint-md\b"
rg "\-\-breakpoint-lg\b"
rg "\-\-breakpoint-xl\b"
rg "\-\-breakpoint-2xl\b"
rg "\-\-container-3xs\b"
rg "\-\-container-2xs\b"
rg "\-\-text-lg--line-height\b"
rg "\-\-text-xl--line-height\b"
rg "\-\-text-2xl--line-height\b"
rg "\-\-text-3xl\b"
rg "\-\-text-3xl--line-height\b"
rg "\-\-text-4xl\b"
rg "\-\-text-4xl--line-height\b"
rg "\-\-text-5xl\b"
rg "\-\-text-5xl--line-height\b"
rg "\-\-text-6xl\b"
rg "\-\-text-6xl--line-height\b"
rg "\-\-text-7xl\b"
rg "\-\-text-7xl--line-height\b"
rg "\-\-text-8xl\b"
rg "\-\-text-8xl--line-height\b"
rg "\-\-text-9xl\b"
rg "\-\-text-9xl--line-height\b"
rg "\-\-font-weight-thin\b"
rg "\-\-font-weight-extralight\b"
rg "\-\-font-weight-light\b"
rg "\-\-font-weight-extrabold\b"
rg "\-\-font-weight-black\b"
rg "\-\-tracking-tighter\b"
rg "\-\-tracking-tight\b"
rg "\-\-tracking-normal\b"
rg "\-\-tracking-wide\b"
rg "\-\-tracking-wider\b"
rg "\-\-tracking-widest\b"
rg "\-\-leading-tight\b"
rg "\-\-leading-snug\b"
rg "\-\-leading-normal\b"
rg "\-\-leading-relaxed\b"
rg "\-\-leading-loose\b"
rg "\-\-radius-xs\b"
rg "\-\-radius-4xl\b"
rg "\-\-shadow-2xs\b"
rg "\-\-shadow-xs\b"
rg "\-\-shadow-sm\b"
rg "\-\-shadow-md\b"
rg "\-\-shadow-lg\b"
rg "\-\-shadow-xl\b"
rg "\-\-shadow-2xl\b"
rg "\-\-inset-shadow-2xs\b"
rg "\-\-inset-shadow-xs\b"
rg "\-\-inset-shadow-sm\b"
rg "\-\-drop-shadow-xs\b"
rg "\-\-drop-shadow-sm\b"
rg "\-\-drop-shadow-md\b"
rg "\-\-drop-shadow-lg\b"
rg "\-\-drop-shadow-xl\b"
rg "\-\-drop-shadow-2xl\b"
rg "\-\-animate-spin\b"
rg "\-\-animate-ping\b"
rg "\-\-animate-pulse\b"
rg "\-\-animate-bounce\b"
rg "\-\-blur-xs\b"
rg "\-\-blur-sm\b"
rg "\-\-blur-lg\b"
rg "\-\-blur-2xl\b"
rg "\-\-blur-3xl\b"
rg "\-\-perspective-dramatic\b"
rg "\-\-perspective-near\b"
rg "\-\-perspective-normal\b"
rg "\-\-perspective-midrange\b"
rg "\-\-perspective-distant\b"
rg "\-\-aspect-video\b"
```

</details>

The only exception I noticed is that we have this:
```css
src/typography.utilities.css
10:  @media (width >= theme(--breakpoint-sm)) {
```
But this is not a variable, but it's replaced at build time with the
actual value, so this is not a real issue.

Testing on other templates:

<img width="2968" alt="image"
src="https://github.com/user-attachments/assets/cabf121d-4cb9-468f-9cf5-ceb02609dc7d"
/>


Fixes: https://github.com/tailwindlabs/tailwindcss/issues/16145

---------

Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2025-02-07 17:12:47 +00:00
Robin Malfait
83fdf373aa
Prepare v4.0.4 (#16302)
Co-authored-by: Adam Wathan <adam.wathan@gmail.com>
2025-02-06 15:18:11 +01:00
Robin Malfait
b7c3f50143
Prepare v4.0.3 (#16146) 2025-02-01 12:38:55 +01:00
Robin Malfait
50bafce756
Prepare for v4.0.2 release (#16131)
Co-authored-by: Adam Wathan <adam.wathan@gmail.com>
2025-01-31 19:30:36 +01:00
Robin Malfait
0d5e2be312
Ensure we process Tailwind CSS features when using @reference (#16057)
This PR fixes an issue where if you only used `@reference` that we
didn't process Tailwind CSS features.

We have a 'quick bail check', in the PostCSS plugin to quickly bail if
we _konw_ that we don't need to handle any Tailwind CSS features. This
is useful in Next.js applications where every single CSS file will be
passed to the PostCSS plugin.

If you use custom font ins Next.js, each of those fonts will have a CSS
file as well.

Before we introduced `@reference`, we used `@import "tailwindcss"
reference`, which passed the bail check because `@import` was being
used. Now we have `@reference` which wasn't included in the list.

This is now solved.

Fixes: #16056


### Test plan

Added a failing test that is now failing after the fix.
2025-01-30 15:29:08 +00:00
Philipp Spiess
06552092bd
Prepare v4.0.1 release (#16018)
Co-authored-by: Adam Wathan <adam.wathan@gmail.com>
2025-01-29 14:14:35 -05:00
Hugo van Rijswijk
9fef2bde50
Add :host rule to @theme layer (#15975)
Resolves #15799
Resolves #14478
Part-of #15005

Adds a `:host` selector for the `@theme` layer. This is necessary for
the `@theme` layer to work correctly in shadow DOM.

Also updates the snapshots for the tests that were affected by this
change (in a separate commit).

## Test plan

Tested via the Vite playground:

<img width="1121" alt="Screenshot 2025-01-29 at 15 06 49"
src="https://github.com/user-attachments/assets/a7908135-5ff8-472f-a053-d2c6d5c81e1b"
/>

Additionally made sure that `@property` defaults also work across
Firefox, Chrome, and Safari (the `@property` definition from the root is
pulled in) and added a UI spec.

---------

Co-authored-by: Philipp Spiess <hello@philippspiess.com>
2025-01-29 17:20:29 +01:00
Jordan Pittman
a8c54acaba
Prepare v4.0.0 release (#15693) 2025-01-21 20:58:59 +00:00
Robin Malfait
8a97a6a8d9
v4.0.0-beta.10 (#15691)
Co-authored-by: Adam Wathan <adam.wathan@gmail.com>
2025-01-21 16:19:28 +00:00
Philipp Spiess
2de644b20e
Remove @property fallbacks for Firefox (#15622)
This PR removes the `@property` fallbacks added in #13655. This is
possible because we're targeting a minimum Firefox version of 128 which
[includes support for \`@property\`
rules](https://developer.mozilla.org/de/docs/Web/CSS/@property).

<img width="1284" alt="Screenshot 2025-01-14 at 11 36 44"
src="https://github.com/user-attachments/assets/ae070781-35c1-4165-be51-baa63f28db5b"
/>
2025-01-14 15:51:44 +01:00
Philipp Spiess
acd2da5247
Upgrade lightningcss to 1.29.1 (#15593)
Upgrading `lightningcss` to fix invalid `list-style: none` conversion.
I've also reverted the change to preflight while at it, since it's no
longer necessary.
2025-01-10 14:09:13 +01:00
Robin Malfait
aac8c5a12a
Prepare v4.0.0-beta.9 release (#15583)
Co-authored-by: Adam Wathan <adam.wathan@gmail.com>
2025-01-09 17:04:34 +00:00
Philipp Spiess
a11c80d6c6
Upgrade lightningcss to 1.29.0 (#15576)
Closes #15438
Closes #15560
Closes #15561
Closes #15562

This PR upgrades `lightningcss` to `1.29.0` and uses the [new feature
flag](304389600f)
to disable the light-dark function transpilation.
2025-01-09 17:14:48 +01:00
Jordan Pittman
7bf11f9087
Move --container-prose to --max-width-prose (#15439)
We don’t want utilities like `basis-prose`, `w-prose`, etc existing nor
a `@prose:*` variant. So we’re moving the theme key to `--max-width-*`
to align with the definition as it was in v3.

cc @adamwathan

---------

Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-12-18 20:15:37 -05:00
Robin Malfait
c9dfe17cac
Prepare v4.0.0-beta.8 release (#15418) 2024-12-17 13:31:28 +01:00
Robin Malfait
0072f01376
Prepare v4.0.0-beta.7 release (#15392)
Co-authored-by: Adam Wathan <adam.wathan@gmail.com>
2024-12-13 14:18:21 +00:00
Philipp Spiess
04dcf27de5
Change Chrome target to 111 (#15389)
Resolves https://github.com/tailwindlabs/tailwindcss/discussions/15387

This PR changes the Chrome target to 111. We initially picked 120
because of the unnecessary `:dir()` down-leveling but we that was maybe
a bit too recent as it was causing some necessary prefixes to not be
generated (e.g. `-webkit-background-clip`).

This PR changes it to 111 which we require for the `color-mix()`
function. To work around the `:dir()` down-leveling we also disable the
`DirSelector` lightningcss feature which is used to control this
behavior:
https://sourcegraph.com/github.com/parcel-bundler/lightningcss/-/blob/src/selector.rs?L1964-1965
2024-12-13 15:07:04 +01:00
Robin Malfait
bcf70990a7
Improve debug logs (#15303)
This PR improves the debug logs for the `@tailwindcss/postcss`
integration. It uses custom instrumentation to provide a nested but
detailed overview of where time is spent during the build process.

The updated logs look like this:
```
[0.15ms] [@tailwindcss/postcss] src/app/geistsans_9fc57718.module.css
[0.14ms]   ↳ Quick bail check
[0.02ms] [@tailwindcss/postcss] src/app/geistsans_9fc57718.module.css
[0.01ms]   ↳ Quick bail check

[0.03ms] [@tailwindcss/postcss] src/app/geistmono_b9f59162.module.css
[0.02ms]   ↳ Quick bail check
[0.12ms] [@tailwindcss/postcss] src/app/geistmono_b9f59162.module.css
[0.11ms]   ↳ Quick bail check

[42.09ms] [@tailwindcss/postcss] src/app/globals.css
[ 0.01ms]   ↳ Quick bail check
[12.12ms]   ↳ Setup compiler
[ 0.11ms]     ↳ PostCSS AST -> Tailwind CSS AST
[11.99ms]     ↳ Create compiler
[ 0.07ms]   ↳ Register full rebuild paths
[ 0.06ms]   ↳ Setup scanner
[ 7.51ms]   ↳ Scan for candidates
[ 5.86ms]   ↳ Register dependency messages
[ 5.88ms]   ↳ Build utilities
[ 8.34ms]   ↳ Optimization
[ 0.23ms]     ↳ AST -> CSS
[ 4.20ms]     ↳ Lightning CSS
[ 3.89ms]     ↳ CSS -> PostCSS AST
[ 1.97ms]   ↳ Update PostCSS AST
```
2024-12-11 15:27:20 +01:00
Jonathan Reinink
2cbc915193
Rename --aspect-ratio-* theme key to --aspect-* (#15365)
This PR renames the `--aspect-ratio` theme key to `--aspect`. This is to
match what we've done with other theme keys where they match the utility
names, like `--ease` and `--leading`.

```diff
  @theme {
-   --aspect-ratio-retro: 4 / 3;
+   --aspect-retro: 4 / 3;
  }
```

Additionally, I've also converted the existing `aspect-video` static
utility to a theme value. This will allow people to override this
utility in their own projects—something that's not possible with static
utilities. This change feels appropriate since the video aspect ratio is
subjective, unlike other static utilities like `aspect-square`.

```css
@theme {
  --aspect-video: 4 / 3; /* N64 baby! */
}
```
2024-12-10 14:33:20 -05:00
Robin Malfait
d444362d5e
Skip creating a compiler for CSS files that should not be processed (#15340)
This PR skips creating a compiler in the `@tailwindcss/postcss`
implementation if we know that the CSS file we are handling is
definitely not a Tailwind CSS file.

This is a performance improvement for initial builds where some CSS
files would've been handling by Tailwind CSS but shouldn't. E.g.: When
setting up custom fonts in Next.js applications, each font will have
it's own CSS file that is passed to `@tailwindcss/postcss`.

Since they don't contain `@import` or any other Tailwind CSS directives,
we can just skip them.
2024-12-09 11:55:33 +01:00
Philipp Spiess
94a3cff687
Fix PostCSS watcher warnings on Windows (#15321)
Resolves #15320
Resolves #15175

Turns out that the postcss file watcher does not like our Unix based
paths and will print a warning about them. This fixes the issue by
calling `path.resolve()` to convert it back to a Windows-style absolute
path if necessary.

## Test Plan

Tested on Windows with a new Next.js 14 project. Ensured that file
reloads also still work (changes to the `tsx` file are picked up
correctly). Also ensure that the CI runs on Windows.

### Before

<img width="1178" alt="Screenshot 2024-12-06 at 13 12 23"
src="https://github.com/user-attachments/assets/70c1fe45-6983-4fb4-9889-716a0cbef03a">

### After

<img width="1196" alt="Screenshot 2024-12-06 at 13 23 24"
src="https://github.com/user-attachments/assets/0b9e3ff7-c5b6-4ccb-85a9-e7ba7aee355a">
2024-12-09 10:44:25 +01:00
Jordan Pittman
3d0b86c7d2
Prepare v4.0.0-beta.6 release (#15325) 2024-12-06 14:32:21 -05:00
Philipp Spiess
85da88f851
Prepare v4.0.0-beta.5 (#15285)
Co-authored-by: Adam Wathan <adam.wathan@gmail.com>
2024-12-04 16:28:16 +01:00
Robin Malfait
408fa99849
Use AST transformations in @tailwindcss/postcss (#15297)
This PR improves the `@tailwindcss/postcss` integration by using direct
AST transformations between our own AST and PostCSS's AST. This allows
us to skip a step where we convert our AST into a string, then parse it
back into a PostCSS AST.

The only downside is that we still have to print the AST into a string
if we want to optimize the CSS using Lightning CSS. Luckily this only
happens in production (`NODE_ENV=production`).

This also introduces a new private `compileAst` API, that allows us to
accept an AST as the input. This allows us to skip the PostCSS AST ->
string -> parse into our own AST step.

To summarize:

Instead of:
- Input: `PostCSS AST` -> `.toString()` -> `CSS.parse(…)` -> `Tailwind
CSS AST`
- Output: `Tailwind CSS AST` -> `toCSS(ast)` -> `postcss.parse(…)` ->
`PostCSS AST`

We will now do this instead:
- Input: `PostCSS AST` -> `transform(…)` -> `Tailwind CSS AST`
- Output: `Tailwind CSS AST` -> `transform(…)` -> `PostCSS AST`


---

Running this on Catalyst, the time spent in the `@tailwindcss/postcss`
looks like this:
- Before: median time per run: 19.407687 ms
- After: median time per run: 11.8796455 ms

This is tested on Catalyst which roughly generates ~208kb worth of CSS
in dev mode.

While it's not a lot, skipping the stringification and parsing seems to
improve this step by ~40%.

Note: these times exclude scanning the actual candidates and only time
the work needed for parsing/stringifying the CSS from and into ASTs. The
actual numbers are a bit higher because of the Oxide scanner reading
files from disk. But since that part is going to be there no matter
what, it's not fair to include it in this benchmark.

---------

Co-authored-by: Jordan Pittman <jordan@cryptica.me>
2024-12-04 15:43:59 +01:00
Philipp Spiess
545401469d
Postcss: Run plugin in Once hook (#15273)
Closes #15138

This PR changes the postcss client to run in the `Once` hook instead of
`OnceExit`. This makes sure the postcss order in v4 matches that of v3.

Conceptually this also makes more sense, since we expect tailwindcss to
be run as one of the first plugins in the pipeline (where `OnceExit`
would run it almost at the end).

To make sure it's still possible to use `postcss-import` before and have
it resolve to the right paths, we also needed to change the
`postcss-fix-relative-paths` plugin to run in the `Once` order
(`postcss-import` also uses `Once` order so the order).

## Test Plan

This issue had many ways in which it can manifest. I added a unit test
to ensure the plugin order works but here's a concrete example when
using the postcss plugin in Vite.

### Before

Image `url()`s were not properly handled since the postcss plugin to
transform these was run before Tailwind CSS could generate the class for
it:

<img width="2532" alt="Screenshot 2024-12-02 at 14 55 42"
src="https://github.com/user-attachments/assets/2f23b409-1576-441d-9ffe-6f24ad6e7436">

### After

<img width="2529" alt="Screenshot 2024-12-02 at 14 53 52"
src="https://github.com/user-attachments/assets/b754c3d8-1af1-4aeb-87da-0bfc3ffecdb7">

---------

Co-authored-by: Jordan Pittman <jordan@cryptica.me>
2024-12-03 10:28:51 +01:00
Robin Malfait
973650624d
Prepare v4.0.0-beta.4 (#15245) 2024-11-29 17:18:42 +01:00
Robin Malfait
99b73ee368
Improve performance of @tailwindcss/postcss and @tailwindcss/vite (#15226)
This PR improves the performance of the `@tailwindcss/postcss` and
`@tailwindcss/vite` implementations.

The issue is that in some scenarios, if you have multiple `.css` files,
then all of the CSS files are ran through the Tailwind CSS compiler. The
issue with this is that in a lot of cases, the CSS files aren't even
related to Tailwind CSS at all.

E.g.: in a Next.js project, if you use the `next/font/local` tool, then
every font you used will be in a separate CSS file. This means that we
run Tailwind CSS in all these files as well.

That said, running Tailwind CSS on these files isn't the end of the
world because we still need to handle `@import` in case `@tailwind
utilities` is being used. However, we also run the auto source detection
logic for every CSS file in the system. This part is bad.

To solve this, this PR introduces an internal `features` to collect what
CSS features are used throughout the system (`@import`, `@plugin`,
`@apply`, `@tailwind utilities`, etc…)

The `@tailwindcss/postcss` and `@tailwindcss/vite` plugin can use that
information to decide if they can take some shortcuts or not.

---

Overall, this means that we don't run the slow parts of Tailwind CSS if
we don't need to.

---------

Co-authored-by: Adam Wathan <adam.wathan@gmail.com>
2024-11-29 10:59:29 -05:00
Philipp Spiess
6abd8086c3 Prepare v4.0.0-beta.3 (#15217)
Co-authored-by: Adam Wathan <adam.wathan@gmail.com>
2024-11-27 18:25:37 +01:00
Adam Wathan
aa15964b28
Use unitless line-heights for font-size variables (#15216)
Safari has an [insane
bug](https://github.com/tailwindlabs/tailwindcss/issues/15196) where if
you register custom properties for gradient colors using the `"<color>"`
type, you attempt to transition a gradient on an element, _and_ you set
a font-size and line-height on that element that point to CSS variables
defined using `rem` units, the element size changes and shifts the
layout while the transition is happening:


https://github.com/user-attachments/assets/46eefccf-8a12-4751-8a44-54e48c54cd06

This bug goes away if you use anything other than `rem` units for the
line-height. So this PR changes all of our variables like
`--text-3xl--line-height` to use unitless relative line-height values
instead of fixed line-height values to workaround this bug. Not my
favorite change but pretty low impact because you likely aren't going to
reference those variables for much anyways.

If Safari ever fixes this bug (which is still present as of Safari 18),
it would be nice to swap these back to what they were.

Fixes #15196.

---------

Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-11-27 11:39:04 -05:00
Adam Wathan
961e8da8fd
Use oklab instead of oklch for color-mix(…) and gradients (#15201)
Fixes https://github.com/tailwindlabs/tailwindcss/discussions/15184,
https://github.com/tailwindlabs/tailwindcss/issues/14955

There's a strange bug in Safari < 18 where mixing a color with
`transparent` or with a gray tone, the resulting color looks as if it's
been interpolated through a red-ish color.

Here's the same blue to transparent gradient in Safari 17 using OKLAB
and OKLCH for comparison:

<img width="747" alt="image"
src="https://github.com/user-attachments/assets/1cb09b00-0d84-4284-be34-103726d8af03">

In other browsers, both of these examples look identical.

This bug also shows up when using an opacity modifier right now because
we use `in oklch` in our `color-mix(…)` calls:

<img width="744" alt="image"
src="https://github.com/user-attachments/assets/b029c5f1-0c5c-4119-80ba-dfeabe25927e">

This PR updates all of the affected places in Tailwind to use `in oklab`
instead of `in oklch` which then renders everything as expected in all
browsers.

The big unfortunate change here is changing the default behavior of
gradient utilities like `bg-linear-to-r` to use `in oklab` instead of
`in oklch`. This means you get muddier gradients by default when
creating a gradient between two regular colors (no transparent or gray),
like how they looked in v3:

<img width="740" alt="image"
src="https://github.com/user-attachments/assets/d02e7596-4c99-4ba3-b929-d2db4911c8e9">

This feels worth it though to avoid people getting bitten by this Safari
bug without realizing it, and people can always opt in to using OKLCH
with classes like `bg-linear-to-r/oklch`. The nice thing about making
this opt-in is that no one will opt-in to this when using transparent or
gray because it won't make things look any different/better, and the
only places where it does make things look better _do_ work as expected
in Safari anyways.

---------

Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-11-27 06:18:31 -05:00
Philipp Spiess
cb518f4623
Set browser targets for iOS Safari, Firefox, and Chrome (#15166)
Closes #15160

We need to set browser targets for each browser individually to see
vendor prefixes created for each browser.

Exact values are up for discussion, this first pass is taken from
@adamwathan's comments in
https://github.com/tailwindlabs/tailwindcss/issues/15160

---------

Co-authored-by: Adam Wathan <adam.wathan@gmail.com>
2024-11-26 11:22:12 +00:00
Jordan Pittman
bd43d63df2
Prepare v4.0.0-beta.2 release (#15104)
Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-11-22 11:17:21 -05:00
Jonathan Reinink
dad9ac6209
Revert new default form styles (#15100)
Closes #15071

This PR reverts the changes in #15036 which add consistent base styles
for buttons and form controls to Preflight.

While this felt like a good idea (for the reasons explained in that PR),
practically this is just too disruptive of a change for people upgrading
from v3 to v4.

While updating some of our projects to v4 we found ourselves adding
classes to undo styles more often than we expected, and it also felt
inconsistent to have to use a different set of classes to style a link
or a button when we wanted them to look the same.

We also decided it feels a little strange that you could change the
border color of an element without ever specifying that it should have a
border, for example this just feels a little wrong:

```html
<button class="border-blue-500">
```

We also needed to set a default `color-scheme` value for any of this
stuff to work which breaks the ability to use the `color-scheme` meta
tag.

Since this change was a fairly major breaking change and we aren't
feeling much benefit from it, it doesn't feel worth making this change
for v4.

---------

Co-authored-by: Philipp Spiess <hello@philippspiess.com>
2024-11-22 08:55:05 -05:00
Jordan Pittman
5e4f565fe4
Prepare v4.0.0-beta.1 release (#15070) 2024-11-21 13:20:30 -05:00
Robin Malfait
11dce5af48
v4.0.0-alpha.36 (#15062)
Prepare v4.0.0-alpha.36
2024-11-21 14:20:56 +01:00
Jordan Pittman
4f63a5a9e0
Inline theme values in drop-shadow (#15056)
This PR updates the default `drop-shadow-*` values to use a single
shadow instead of multiple shadows.

This ensures that the usage with `drop-shadow(var(--drop-shadow-xl))` is
correct because the `drop-shadow(…)` needs to encode a single drop
shadow.

---------

Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
2024-11-21 13:13:38 +01:00
Philipp Spiess
fcf948f8c8
Add consistent base styles for buttons and form controls (#15036)
This PR introduces consistent base styles for buttons and form controls
in Tailwind CSS v4.

## Motivation

In v3, form elements lack default styles, which can be
confusing—especially when certain elements, like a text input without a
placeholder or value, are rendered completely invisible on the page.

The goal of this change is to provide reasonable default styles for
buttons, inputs, selects, and textareas that are (mostly) consistent
across all browsers while remaining easy to customize with your own
styles.

This improvement should make Tailwind more accessible for developers new
to the framework and more convenient in scenarios where you need to
quickly create demos (e.g., using Tailwind Play).

## Light and dark mode support

These styles support both light and dark mode, achieved using the
`light-dark()` CSS function. While browser support for this function is
still somewhat limited, Lightning CSS transpiles it to a CSS
variable-based approach that works in older browsers.

For this approach to function correctly, a default `color-scheme` must
be set in your CSS (as explained in [the Lightning CSS
documentation](https://lightningcss.dev/transpilation.html#light-dark()-color-function)).
This PR addresses this requirement by setting the `color-scheme` to
`light` on the `html` element in Preflight.

<img width="1712" alt="image"
src="https://github.com/user-attachments/assets/dba56368-1427-47b3-9419-7c2f6313a944">

<img width="1709" alt="image"
src="https://github.com/user-attachments/assets/3d84fcd2-9606-4626-8e03-164a1dce9018">

## Breaking changes

While we don’t expect these changes to significantly impact v3 users
upgrading to v4, there may be minor differences for those relying on the
simpler v3 styles.

For example, Preflight now applies a `border-radius` to buttons and form
controls. If you weren’t explicitly setting the border radius to `0` in
your project, you’ll need to do so to restore the previous look.

Thankfully, reverting to the v3 styles is straightforward—just add the
following reset to your CSS:

```css
@layer base {
  input,
  textarea,
  select,
  button {
    border: 0px solid;
    border-radius: 0;
    padding: 0;
    background-color: transparent;
  }
}
```

It’s worth noting that this reset doesn't touch the
`::file-selector-button` styles that were added in this PR. This is
because it's not possible to reliably "undo" these styles and restore
the original user-agent styles (which is what was used in v3), as these
are different in each browser. However, these new styles actually match
the defaults in most browsers pretty closely, so hopefully this just
won't be an issue.

## Codemod

This PR includes a codemod that automatically inserts the above
mentioned v3 reset to help avoid breaking changes during the upgrade.
The codemod will insert the following CSS:

```css
/*
  In Tailwind CSS v4, basic styles are applied to form elements by default. To
  maintain compatibility with v3, the following resets have been added:
*/
@layer base {
  input,
  textarea,
  select,
  button {
    border: 0px solid;
    border-radius: 0;
    padding: 0;
    background-color: transparent;
  }
}
```

## Testing

These changes have been tested across a wide range of browsers,
including Chrome, Safari, Firefox, Edge, and Opera on macOS and Windows,
as well as Safari, Chrome, Firefox, and several lesser-known browsers on
iOS and Android.

However, some quirks still exist in certain mobile browsers, such as iOS
Safari, which adds too much bottom padding below date and time inputs:

<img width="1548" alt="Screenshot 2024-11-20 at 3 57 20 PM"
src="https://github.com/user-attachments/assets/507c7724-ac41-4634-a2b3-61ac4917ebce">

The only reliable way to address these issues is by applying
`appearance: none` to these form controls. However, this felt too
opinionated for Preflight, so we’ve opted to leave such adjustments to
user-land implementations.

---------

Co-authored-by: Jonathan Reinink <jonathan@reinink.ca>
Co-authored-by: Jordan Pittman <jordan@cryptica.me>
2024-11-21 11:21:31 +01:00
Philipp Spiess
ae249c7e56
Fix Next.js endless loop when setting a custom distDir (#15053)
Closes #15050

In Tailwind CSS v4 Alpha 31 we changed how we scan template files. This
changes included a new folder-dependency that is emitted for the `base`
directory, so we can listen for new files being added as part of the
postcss dependency.

In our testing, this worked fine with the Next.js integration meaning a
new file in the project root would be picked up by Oxide and we could
update the CSS files accordingly.

This change is now, however, causing an issue. With Next.js 15 **and
with a custom `distDir` configured**, the postcss build, that will write
into the `distDir`, will cause another postcss run to be triggered,
starting an endless loop (regardless of wether or not the `distDir` was
also part of your gitignore list).

This PR now changes the postcss client to not emit the base directory as
a dependency to revert this changes. This does mean that new files and
folders created _directly in the project root_ will require a restart of
the Next.js server again (just like it did in Alpha 31 and before) for
now.

## Test Plan

Next 15 does not seem to run in our current integration test setup (for
some reason the server does not close correctly and it will fail on the
cleanup step), so this change was tested manually:

- First, clone the [templates
repo](https://github.com/philipp-spiess/tailwindcss-playgrounds) I use
for third party frameworks
- Then, do a full build in the parent repo `tailwindcss` via `pnpm
build`
- Now, install the local tarballs in the `tailwindcss-playgrounds` repo
via `pnpm install`

With this setup I have tested changes to a template file (that causes
new utilities to be added) and the CSS file (that will rebuild properly)
across both `pnpm dev` and `pnpm dev --turbo`. Furthermore integration
tests assert it still works in Next 14 like it did before:


https://github.com/user-attachments/assets/b0ccb3dd-d090-4e4c-97c5-74129a2789be

One thing to make sure of is to include the new `distDir` into the
`.gitignore` file as well, otherwise we will scrape it for changes which
inherently causes an endless loop issue again.

---------

Co-authored-by: Adam Wathan <adam.wathan@gmail.com>
2024-11-21 10:47:27 +01:00
Robin Malfait
8b098fc83d
Prepare v4.0.0-alpha.35 release (#15052) 2024-11-20 11:12:32 +00:00
Philipp Spiess
5edf6c7dc0
Ensure clients pin the tailwindcss version (#15011)
We noticed that in the current alpha 34 release, the `package.json` file
of the `@tailwindcss/node` package only defines `tailwindcss` as a dev
dependency. This makes it very easy for version mismatches to happen
when a v3 version (or an earlier v4 alpha for that matter) was installed
in the same project:

```json
{
  "name": "@tailwindcss/node",
  "version": "4.0.0-alpha.34",
  "description": "A utility-first CSS framework for rapidly building custom user interfaces.",
  "license": "MIT",
  "repository": {
    "type": "git",
    "url": "https://github.com/tailwindlabs/tailwindcss.git",
    "directory": "packages/@tailwindcss-node"
  },
  "bugs": "https://github.com/tailwindlabs/tailwindcss/issues",
  "homepage": "https://tailwindcss.com",
  "files": [
    "dist/"
  ],
  "publishConfig": {
    "provenance": true,
    "access": "public"
  },
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "import": "./dist/index.mjs",
      "require": "./dist/index.js"
    },
    "./require-cache": {
      "types": "./dist/require-cache.d.ts",
      "default": "./dist/require-cache.js"
    },
    "./esm-cache-loader": {
      "types": "./dist/esm-cache.loader.d.mts",
      "default": "./dist/esm-cache.loader.mjs"
    }
  },
  "devDependencies": {
    "tailwindcss": "4.0.0-alpha.34"
  },
  "dependencies": {
    "enhanced-resolve": "^5.17.1",
    "jiti": "^2.0.0-beta.3"
  },
  "scripts": {
    "build": "tsup-node",
    "dev": "pnpm run build -- --watch"
  }
}
```

Furthermore, we were trying to fix issues where our integration test
setup could not install `tailwindcss@3` because of how we did pnpm
overrides.

This PR fixes this by:

- Ensuring every client that calls into `tailwindcss` core marks it as a
version-pinned dependency. You are still required to install
`tailwindcss` in your project along side a client (e.g.
`@tailwindcss/vite`) but we now only use your installed version for
importing the respective `.css` files. For the core logic, we are now
requiring each package to use `tailwindcss` at the same version. This
should help resolve issues like
https://github.com/tailwindlabs/tailwindcss/discussions/14652
- We tried to eliminate the dependency on `tailwindcss` from the
`@tailwindcss/upgrade` package. Unfortunately this is not possible to do
right now because we need to load the CSS files from v4 to create the
right environment. In a future version we could bundle the required CSS
files with `@tailwidncss/upgrade` but it doesn't seem necessary for now.
- We then changed our integration test overrides to only override the
`tailwindcss` package that are dependencies of the known list of
packages that we have `tailwindcss` dependencies on: `@tailwindcss/node`
and `@tailwindcss/upgrade`. This ensures that we can install v3 of
`tailwindcss` in the integration tests and it will work. Something we
want to do for some upgrade tests.

# Test plan

Integration work again. Furthermore we added a quick setup with the CLI
using the local tarballs and ensured it works:

```bash
pnpm init
pnpm install ../../tailwindcss/dist/tailwindcss-cli.tgz 
pnpm install ../../tailwindcss/dist/tailwindcss.tgz 
echo '@import "tailwindcss";' > index.css
echo '<div class="underline"></div>' > index.html
pnpm tailwindcss -i index.css -o out.css
cat out.css
```
2024-11-15 17:18:48 +01:00
Philipp Spiess
953ecd2d19
Prepare v4.0.0-alpha.34 (#15002) 2024-11-14 18:23:40 +01:00