688 Commits

Author SHA1 Message Date
Jordan Pittman
3412a9623d
Add bg-{position,size}-* utilities (#17432)
This PR adds `bg-{position,size}-*` utilities that support arbitrary
values. This exist as the new preferred version of something like this:

```
bg-[120px_120px]
```

Is it size or position (hint: it's the 2nd one).

To override it you'd have to provide a data type:
```
bg-[size:120px_120px]
```


Now you can be more explicit and have better intellisense by writing
these:
```
bg-position-[120px_120px]
bg-size-[120px_120px]
```
2025-03-28 16:40:57 +00:00
Jordan Pittman
ab868c6098
Improve arbitrary value validation when parsing candidates (#17361)
Fixes #17357

This affects the CDN and Play

Now candidates like these no longer parse and emit CSS:
- `[--foo:1rem;--bar:2rem]`
- `[&{color:red}]:flex`
- `data-[a]{color:red}foo[a]:flex`
2025-03-28 12:38:57 -04:00
Jordan Pittman
1b6230f54f
Rework scripting variants (#17431)
This replaces the `scripting`, `scripting-none`, and `scripting-initial`
variants with one `noscript` variant that matches the name of the HTML
`<noscript>` element. The previous `scripting` can then be represented
as `not-noscript` e.g. `not-noscript:flex`.
2025-03-28 12:28:20 -04:00
Jordan Pittman
3e53e25669
Add bg-{top,bottom}-{left,right} utilities (#17378)
We’re using this naming for `mask-*` and `mask-radial-at-*` position
utilities and we want to be consistent. The old ones for
`background-position` will stay but are deprecated

---------

Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
2025-03-27 12:43:02 +01:00
Philipp Spiess
18365fff6c Prepare v4.0.17 release 2025-03-26 12:15:19 +01:00
Robin Malfait
1ef97759e3
Add @source not support (#17255)
This PR adds a new source detection feature: `@source not "…"`. It can
be used to exclude files specifically from your source configuration
without having to think about creating a rule that matches all but the
requested file:

```css
@import "tailwindcss";
@source not "../src/my-tailwind-js-plugin.js";
```

While working on this feature, we noticed that there are multiple places
with different heuristics we used to scan the file system. These are:

- Auto source detection (so the default configuration or an `@source
"./my-dir"`)
- Custom sources ( e.g. `@source "./**/*.bin"` — these contain file
extensions)
- The code to detect updates on the file system

Because of the different heuristics, we were able to construct failing
cases (e.g. when you create a new file into `my-dir` that would be
thrown out by auto-source detection, it'd would actually be scanned). We
were also leaving a lot of performance on the table as the file system
is traversed multiple times for certain problems.

To resolve these issues, we're now unifying all of these systems into
one `ignore` crate walker setup. We also implemented features like
auto-source-detection and the `not` flag as additional _gitignore_ rules
only, avoid the need for a lot of custom code needed to make decisions.

High level, this is what happens after the now:

- We collect all non-negative `@source` rules into a list of _roots_
(that is the source directory for this rule) and optional _globs_ (that
is the actual rules for files in this file). For custom sources (i.e
with a custom `glob`), we add an allowlist rule to the gitignore setup,
so that we can be sure these files are always included.
- For every negative `@source` rule, we create respective ignore rules.
- Furthermore we have a custom filter that ensures files are only read
if they have been changed since the last time they were read.

So, consider the following setup:

```css
/* packages/web/src/index.css */
@import "tailwindcss";
@source "../../lib/ui/**/*.bin";
@source not "../../lib/ui/expensive.bin";
```

This creates a git ignore file that (simplified) looks like this:

```gitignore
# Auto-source rules
*.{exe,node,bin,…}
*.{css,scss,sass,…}
{node_modules,git}/

# Custom sources can overwrite auto-source rules
!lib/ui/**/*.bin

# Negative rules
lib/ui/expensive.bin
```

We then use this information _on top of your existing `.gitignore`
setup_ to resolve files (i.e so if your `.gitignore` contains rules e.g.
`dist/` this line is going to be added _before_ any of the rules lined
out in the example above. This allows negative rules to allow-list your
`.gitignore` rules.

To implement this, we're rely on the `ignore` crate but we had to make
various changes, very specific, to it so we decided to fork the crate.
All changes are prefixed with a `// CHANGED:` block but here are the
most-important ones:

- We added a way to add custom ignore rules that _extend_ (rather than
overwrite) your existing `.gitignore` rules
- We updated the order in which files are resolved and made it so that
more-specific files can allow-list more generic ignore rules.
- We resolved various issues related to adding more than one base path
to the traversal and ensured it works consistent for Linux, macOS, and
Windows.

## Behavioral changes

1. Any custom glob defined via `@source` now wins over your `.gitignore`
file and the auto-content rules.
   - Resolves #16920
3. The `node_modules` and `.git` folders as well as the `.gitignore`
file are now ignored by default (but can be overridden by an explicit
`@source` rule).
   - Resolves #17318
   - Resolves #15882
4. Source paths into ignored-by-default folders (like `node_modules`)
now also win over your `.gitignore` configuration and auto-content
rules.
    -  Resolves #16669
5. Introduced `@source not "…"` to negate any previous rules.
   - Resolves #17058
6. Negative `content` rules in your legacy JavaScript configuration
(e.g. `content: ['!./src']`) now work with v4.
   - Resolves #15943 
7. The order of `@source` definitions matter now, because you can
technically include or negate previous rules. This is similar to your
`.gitingore` file.
9. Rebuilds in watch mode now take the `@source` configuration into
account
   - Resolves #15684

## Combining with other features

Note that the `not` flag is also already compatible with [`@source
inline(…)`](https://github.com/tailwindlabs/tailwindcss/pull/17147)
added in an earlier commit:

```css
@import "tailwindcss";
@source not inline("container");
```

## Test plan

- We added a bunch of oxide unit tests to ensure that the right files
are scanned
- We updated the existing integration tests with new `@source not "…"`
specific examples and updated the existing tests to match the subtle
behavior changes
- We also added a new special tag `[ci-all]` that, when added to the
description of a PR, causes the PR to run unit and integration tests on
all operating systems.

[ci-all]

---------

Co-authored-by: Philipp Spiess <hello@philippspiess.com>
2025-03-25 15:54:41 +01:00
Robin Malfait
1c50b5c16c
Prepare v4.0.16 release (#17372)
Prepare the 4.0.16 release.

~~Also added a commit to mark the `--value('…')` and `--modifier('…')`
with literals strings as an experimental feature (aka not shipped in
this PR). But we can revert that commit if we still want to ship it in
4.0.16 instead of 4.1.~~

---------

Co-authored-by: Philipp Spiess <hello@philippspiess.com>
2025-03-25 15:30:32 +01:00
Jordan Pittman
bd501e8511
Add ::-webkit-details-marker pseudo to marker variant (#17362)
See #17360

This PR updates the `marker` variant to also target the marker present
in `<summary>` elements in WebKit browsers. Chromium uses `::marker` and
is therefore already covered.

---------

Co-authored-by: Philipp Spiess <hello@philippspiess.com>
2025-03-25 13:22:00 +01:00
Philipp Spiess
e8715d081e
Extract keyframe name when followed by comma (#17352)
Fixes #17332

This PR ensures that keyframes are emitted even when they are referenced
following a comma, e.g.:

```css
@theme {
  --animate-test: 500ms both fade-in, 1000ms linear 500ms spin infinite;
                                 /* ^ */

  @keyframes fade-in {
    from {
      opacity: 0%;
    }
    to {
      opacity: 100%;
    }
  }
}
```

## Test plan

Added a unit test to capture the issue from #17332
2025-03-24 12:25:41 +01:00
Rudi Visser
baa016a1c9
Add Input & Output check to CLI (#17311)
Throw an error if the input and output file for the CLI are identical.

---------

Co-authored-by: Philipp Spiess <hello@philippspiess.com>
Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
2025-03-24 12:00:36 +01:00
Philipp Spiess
fac8f7df62
Vite: Emit build dependencies on partial rebuilds (#17347)
Closes #17339

This PR fixes an issue that caused changes to `@import`-ed CSS files to
no longer rebuild the stylesheet after a change was made to a template
file.

The change in the template file causes a fast-path in the Vite plugin
now after changes in 4.0.8: _partial rebuilds_. For that branch we do
not need to re-evaluate your input CSS since we know only the candidate
list changed. However, we still need to emit all build dependencies as
via `addWatchFile(…)`, otherwise Vite will not correctly register
updates for these dependencies anymore.

## Test plan

- Updated the kitchen-sink Vite update tests to ensure that an
`@import`-ed CSS file can be updated even after a partial rebuild.
- Ensure this works in our Vite playground
2025-03-24 11:54:55 +01:00
Jordan Pittman
91c0d56d0f Revert "Temporarily revert changes to `@utility"
This reverts commit 1aab04cebff39a5a1b89ff22c6655cf1f549b7a1.
2025-03-20 17:00:23 -04:00
Jordan Pittman
1aab04cebf Temporarily revert changes to `@utility
The github release workflow is currently broken on the 4.0.15 tag for whatever reason and we need to get the release out
2025-03-20 16:21:48 -04:00
Robin Malfait
250c843341
Add suggestions when --spacing(--value(integer, number)) is used (#17308)
This PR adds suggestions to CSS based functional utilities when the
`--spacing(…)` function is used.

Given this CSS:

```css
@import "tailwindcss";

@theme {
  --spacing: 0.25rem;
  --spacing-custom: 123px;
}

@utility with-custom-spacing-* {
  size: --value(--spacing);
}

@utility with-integer-spacing-* {
  size: --spacing(--value(integer));
}

@utility with-number-spacing-* {
  size: --spacing(--value(number));
}
```
    
And this HTML:
    
```html
<div class="with-custom-spacing-custom"></div>
<div class="with-custom-spacing-0"></div>
<div class="with-custom-spacing-0.5"></div>
<div class="with-custom-spacing-1"></div>
<div class="with-custom-spacing-1.5"></div>

<div class="with-integer-spacing-custom"></div>
<div class="with-integer-spacing-0"></div>
<div class="with-integer-spacing-0.5"></div>
<div class="with-integer-spacing-1"></div>
<div class="with-integer-spacing-1.5"></div>

<div class="with-number-spacing-custom"></div>
<div class="with-number-spacing-0"></div>
<div class="with-number-spacing-0.5"></div>
<div class="with-number-spacing-1"></div>
<div class="with-number-spacing-1.5"></div>
```
    
Play: https://play.tailwindcss.com/tYDaSNiNtS


Then you will see the following suggestions:

```json
[
  "with-custom-spacing-custom",

  "with-integer-spacing-0",
  "with-integer-spacing-1",
  "with-integer-spacing-2",
  "with-integer-spacing-3",
  "with-integer-spacing-4",
  "with-integer-spacing-5",
  "with-integer-spacing-6",
  "with-integer-spacing-7",
  "with-integer-spacing-8",
  "with-integer-spacing-9",
  "with-integer-spacing-10",
  "with-integer-spacing-11",
  "with-integer-spacing-12",
  "with-integer-spacing-14",
  "with-integer-spacing-16",
  "with-integer-spacing-20",
  "with-integer-spacing-24",
  "with-integer-spacing-28",
  "with-integer-spacing-32",
  "with-integer-spacing-36",
  "with-integer-spacing-40",
  "with-integer-spacing-44",
  "with-integer-spacing-48",
  "with-integer-spacing-52",
  "with-integer-spacing-56",
  "with-integer-spacing-60",
  "with-integer-spacing-64",
  "with-integer-spacing-72",
  "with-integer-spacing-80",
  "with-integer-spacing-96",

  "with-number-spacing-0",
  "with-number-spacing-0.5",
  "with-number-spacing-1",
  "with-number-spacing-1.5",
  "with-number-spacing-2",
  "with-number-spacing-2.5",
  "with-number-spacing-3",
  "with-number-spacing-3.5",
  "with-number-spacing-4",
  "with-number-spacing-5",
  "with-number-spacing-6",
  "with-number-spacing-7",
  "with-number-spacing-8",
  "with-number-spacing-9",
  "with-number-spacing-10",
  "with-number-spacing-11",
  "with-number-spacing-12",
  "with-number-spacing-14",
  "with-number-spacing-16",
  "with-number-spacing-20",
  "with-number-spacing-24",
  "with-number-spacing-28",
  "with-number-spacing-32",
  "with-number-spacing-36",
  "with-number-spacing-40",
  "with-number-spacing-44",
  "with-number-spacing-48",
  "with-number-spacing-52",
  "with-number-spacing-56",
  "with-number-spacing-60",
  "with-number-spacing-64",
  "with-number-spacing-72",
  "with-number-spacing-80",
  "with-number-spacing-96"
]
```

This is because `--spacing(--value(number))` will include all default
spacing scale suggestions we use. And `--pacing(--value(integer))` will
include the same list but without the floating point numbers.

Follow up PR for: https://github.com/tailwindlabs/tailwindcss/pull/17304
2025-03-20 19:06:07 +00:00
Robin Malfait
a3316f2ef4
Add support for literal values in --value('…') and --modifier('…') (#17304)
This PR adds support for literal values inside the `--value('…')` and
`--modifier('…')` functions. This allows you to safelist some known
values you want to use:

E.g.:

```css
@utility tab-* {
  tab-size: --value('revert', 'initial');
}
```

This allows you to use `tab-revert` and `tab-initial` for example.
2025-03-20 19:02:02 +00:00
Philipp Spiess
4c57d9f734
Prepare v4.0.15 release (#17302)
<!--

👋 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

-->
2025-03-20 17:51:30 +01:00
Philipp Spiess
40a76e3380
Revert "Don't use color-mix(…) on currentColor (#17247)" and work around Preflight crash (#17306)
Closes #17194.

This reverts commit d6d913ec39e2a4cc0a70e9d21c484c6ed95d40ae.

The initial fix does breaks older versions of Chrome (where text won't
render with a color for the placeholder at all anymore) and the usage of
the _relative colors_ features also means it'll require a much newer
version of Safari/Firefox/Chrome to work correctly. The implementation
was also wrong as it always set alpha to the specific percent instead of
applying it additively (note that this can be fixed with `calc(alpha *
opacity)` though).

Instead we decided to fix this by adding a `@supports` query to
Preflight that only targets browsers that aren't affected by the crash.
We currently use the following workaround:

```css
/*
  Set the default placeholder color to a semi-transparent version of the current text color in browsers that do not
  crash when using `color-mix(…)` with `currentColor`. (https://github.com/tailwindlabs/tailwindcss/issues/17194)
*/

@supports (not (-webkit-appearance: -apple-pay-button)) /* Not Safari */ or
  (contain-intrinsic-size: 1px) /* Safari 17+ */ {
  ::placeholder {
    color: color-mix(in oklab, currentColor 50%, transparent);
  }
}
```

## Test plan

When testing the `color-mix(currentColor)` vs `oklab(from currentColor
…)` we created the following support matrix. I'm extending it with _our
fix_ which is the fix ended up using:

| Browser | Version | `color-mix(… currentColor …)` | `oklab(from
currentColor …)` | `@supports { color-mix(…) }` |
| ------- | ------- | ----------------------------- |
---------------------------- | ------- |
| Chrome | 111 |  |  |  |
| Chrome | 116 |  |  |  |
| Chrome | 131+ |  |  |  |
| Safari | 16.4 | 💥 |  |  |
| Safari | 16.6+ |  |  |  |
| Safari | 18+ |  |  |  |
| Firefox | 128 |  |  |  |
| Firefox | 133 |  |  |  |

Note that on Safari 16, this change makes it so that the browser does
not crash yet it still won't work either. That's because now the browser
will fall back to the default placeholder color instead. We used the
following play to test the fix: https://play.tailwindcss.com/RF1RYbZLKY
2025-03-20 17:43:32 +01:00
Philipp Spiess
3f313b4eb2
Ensure that the CSS file rebuilds if a new CSS variable is used from templates (#17301)
Fixes #17288

This PR fixes an issue where changes in template files that _only mark a
new CSS variable as used_ was not causing the CSS file to rebuilds.

This also fixes a flaky integration test that was caused by a missing
`await` line on the final assertion (causing it to sometimes run the
assertion in time while the test runner was still running).

## Test plan

Turns out we already had an integration test for this but it wasn't
correctly running due to the missing await.
2025-03-20 12:52:02 +01:00
Philipp Spiess
ca7b10e7d3
Make --theme(…) return CSS variables (#17036)
Closes #16945

This PR changes the `--theme(…)` function now return CSS `var(…)`
definitions unless used in places where `var(…)` is not valid CSS (e.g.
in `@media (width >= theme(--breakpoint-md))`):

```css
/* input */
@theme {
  --color-red: red;
}
.red {
  color: --theme(--color-red);
}

/* output */
:root, :host {
  --color-red: red;
}
.red {
  color: var(--color-red);
}
```

Furthermore, this adds an `--theme(… inline)` option to the `--theme(…)`
function to force the resolution to be inline, e.g.:

```css
/* input */
@theme {
  --color-red: red;
}
.red {
  color: --theme(--color-red inline);
}

/* output */
.red {
  color: red;
}
```

This PR also changes preflight and the default theme to use this new
`--theme(…)` function to ensure variables are prefixed correctly.

## Test plan

- Added unit tests and a test that pulls in the whole preflight under a
prefix theme.
2025-03-20 12:51:22 +01:00
Philipp Spiess
a1acaeeee0
Export PluginUtils from tailwindcss/plugin (#17299)
Closes #17293

We used to export this in v3 so might as well bring it back for the
`tailwindcss/plugin` export list.
2025-03-20 12:19:45 +01:00
Philipp Spiess
503bad4e75
Use bun-baseline for all x64 builds (#17267)
Closes #17259

This PR now also updates the MacOS x64 build to use `bun-baseline`,
meaning all x64 builds now use baseline for the improved hardware
compatibility.

Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
2025-03-20 12:16:04 +01:00
Robin Malfait
d698c10836
Ensure multiple --value(…) or --modifier(…) calls don't delete subsequent declarations (#17273)
This PR fixes a bug in the handling of `@utility`. Essentially if you
had a declaration where you used a `--modifier(…)` _and_ a `--value(…)`
and both caused the declaration to be removed, the declaration after the
current one would be removed as well.

This happened because 2 reasons:

1. Once we removed the declaration when we handled `--modifier(…)`, we
didn't stop the walk and kept going.
2. The `replaceWith(…)` code allows you to call the function multiple
times but immediately mutates the AST. This means that if you call it
multiple times that you are potentially removing / updating nodes
followed by the current one.

E.g.:

```css
@utility mask-r-* {
  --mask-right: linear-gradient(to left, transparent, black --value(percentage));
  --mask-right: linear-gradient(
    to left,
    transparent calc(var(--spacing) * --modifier(integer)),
    black calc(var(--spacing) * --value(integer))
  );
  mask-image: var(--mask-linear), var(--mask-radial), var(--mask-conic);
}
```

If this is used as `mask-r-10%`, then the first definition of
`--mask-right` is kept, but the second definition of `--mask-right` is
deleted because both `--modifier(integer)` and `--value(integer)` do not
result in a valid value.

However, the `mask-image` declaration was also removed because the
`replaceWith(…)` function was called twice. Once for
`--modifier(integer)` and once for `--value(integer)`.

# Test plan

1. Added a test to cover this case.
2. Existing tests pass.
3. Added a hard error if we call `replaceWith(…)` multiple times.
2025-03-19 13:25:53 +00:00
Martijn Cuppens
1564bf092b
Remove redundant line-height from body (#15212)
It was added in #2729 to override line heights set on the body by
modern-normalize. However, it appears that modern-normalize never
included any line-height definitions—only a font-family rule was
present.

Ref:
https://github.com/sindresorhus/modern-normalize/blob/v1.1.0/modern-normalize.css

---------

Co-authored-by: Philipp Spiess <hello@philippspiess.com>
2025-03-18 12:23:49 +01:00
Benoît Rouleau
ebfde316e1
Add safe alignment utilities (#14607)
Fixes #7929 and #12916

This PR adds [safe alignment
utilities](https://www.stefanjudis.com/today-i-learned/safe-unsafe-alignment-in-css-flexbox/)
to Tailwind 4. I opted to include them for every justify/align
content/items/self property, but only for the `end` and `center` values.
I know that it doesn't make sense for `start` (as the point of safe
alignment is to fall back to `start` when it overflows), but I'm not
sure about `space-between`, `space-around`, or other values. I certainly
never encountered a situation where I needed `safe` with those.
2025-03-17 14:09:15 +01:00
Bendegúz Hajnal
1d2d50ee66
Add items-baseline-last utility (#13888)
This PR adds the `items-first-baseline` and `items-last-baseline`
utility classes that can control
[`baseline-position`](https://developer.mozilla.org/en-US/docs/Web/CSS/align-items#formal_syntax)
for the [align-items
property](https://developer.mozilla.org/en-US/docs/Web/CSS/align-items#baseline).

Browser support:
- MDN:
https://developer.mozilla.org/en-US/docs/Web/CSS/align-items#browser_compatibility
- Can I use `first baseline`:
https://caniuse.com/?search=align%20items%3A%20first%20baseline
- Can I use `last baseline`:
https://caniuse.com/?search=align%20items%3A%20last%20baseline

The feature were requested multiple times:

- https://github.com/tailwindlabs/tailwindcss/discussions/13518
- https://github.com/tailwindlabs/tailwindcss/discussions/12406
- https://github.com/tailwindlabs/tailwindcss/discussions/11623
- https://github.com/tailwindlabs/tailwindcss/discussions/4855

---------

Co-authored-by: Philipp Spiess <hello@philippspiess.com>
2025-03-17 13:51:13 +01:00
Philipp Spiess
d6d913ec39
Don't use color-mix(…) on currentColor (#17247)
Closes #17194

This PR works around a crash when rendering opacity on `currentColor`
(as used by the placeholder styles in preflight) on Safari 16.4 and
Safari 16.5. Unfortunately it seems that the [`color-mix(…)` function is
not compatible with `currentColor` for these versions of
Safari](https://stackoverflow.com/questions/76436497/the-color-mix-property-involving-currentcolor-causes-safari-to-crash).
We tried a few different ways to work around this without success:

- Using an `@supports` media query to target these Safari versions and
overwriting the placeholder still makes these browsers crash.
- Changing the way we apply opacity to `currentColor` in core doesn't
seem to work for non-placeholder values:
https://github.com/tailwindlabs/tailwindcss/issues/17194#issuecomment-2728949181
However, a wrong opacity is still better than a complete browser crash.

The work-around of using the `oklab(…)` function does seem to work for
`::placeholder` styles in preflight though according to our testing so
this PR applies this change to preflight.

## Test plan

- See https://play.tailwindcss.com/WSsSTLHu8h?file=css 
- Tested on Chrome/Safari 16.4/Safari 18.3/Firefox

<img width="564" alt="Screenshot 2025-03-17 at 11 32 47"
src="https://github.com/user-attachments/assets/cfd0db71-f39a-4bc0-bade-cea70afe50ae"
/>
2025-03-17 13:23:02 +01:00
Robin Malfait
448949318e
Fix inferring data type of border-[…] with multiple values (#17248)
This PR fixes an issue where arbitrary values such as
`border-[12px_4px]` were incorrectly producing `border-color` instead of
`border-width` values.

To solve it, I extended the `<line-width>` check to make sure that every
part of the value is a valid `<line-width>`.

In order for a `line-width` to be valid, every part should be one of:

1. A keyword: `thin`, `medium`, `thick`
2. A length: `12px`
3. A number: `0`

Fixes: #17221

# Test plan

1. Added test to verify this works
2. All existing tests pass
2025-03-17 12:35:55 +01:00
Jordan Pittman
50562a9c94
Fix -bg-conic-* utilities (#17174)
The negative versions were missing the `deg` in `<number>deg` so they
didn’t work whoops
2025-03-13 10:13:56 -04:00
Robin Malfait
3c5903c1ee
Prepare v4.0.14 release (#17173) 2025-03-13 12:36:34 +01:00
Philipp Spiess
74ccde4672
Upgrade lightningcss to 1.29.2 in Standalone (#17169)
Closes #17162
Closes #17163
Closes #17164
Closes #17165
Closes #17166
Closes #17167

Noticed that there was a second place pulling in the lightningcss
version numbers that wasn't covered by the previous upgrade PR.
Thankfully the APIs of the node bindings are still compatible.

To avoid this mistake in the future I also exported these sub-packages
as a workspace dependency so all the version strings appear right next
to each other.
2025-03-13 11:18:06 +01:00
Philipp Spiess
215f4f348b
Add @source inline(…) (#17147)
This PR adds a new experimental feature that can be used to force-inline
utilities based on an input string. The idea is that all utilities
matching the source string will be included in your CSS:

```css
/* input.css */
@source inline('underline');

/* output.css */
.underline {
   text-decoration: underline;
}
```

Additionally, the source input is brace-expanded, meaning you can use
one line to inline a whole namespace easily:
```css
/* input.css */
@source inline('{hover:,}bg-red-{50,{100..900..100},950}');

/* output.css */
.bg-red-50 {
  background-color: var(--color-red-50);
}
.bg-red-100 {
  background-color: var(--color-red-100);
}
.bg-red-200 {
  background-color: var(--color-red-200);
}
.bg-red-300 {
  background-color: var(--color-red-300);
}
.bg-red-400 {
  background-color: var(--color-red-400);
}
.bg-red-500 {
  background-color: var(--color-red-500);
}
.bg-red-600 {
  background-color: var(--color-red-600);
}
.bg-red-700 {
  background-color: var(--color-red-700);
}
.bg-red-800 {
  background-color: var(--color-red-800);
}
.bg-red-900 {
  background-color: var(--color-red-900);
}
.bg-red-950 {
  background-color: var(--color-red-950);
}
@media (hover: hover) {
  .hover\\:bg-red-50:hover {
    background-color: var(--color-red-50);
  }
  .hover\\:bg-red-100:hover {
    background-color: var(--color-red-100);
  }
  .hover\\:bg-red-200:hover {
    background-color: var(--color-red-200);
  }
  .hover\\:bg-red-300:hover {
    background-color: var(--color-red-300);
  }
  .hover\\:bg-red-400:hover {
    background-color: var(--color-red-400);
  }
  .hover\\:bg-red-500:hover {
    background-color: var(--color-red-500);
  }
  .hover\\:bg-red-600:hover {
    background-color: var(--color-red-600);
  }
  .hover\\:bg-red-700:hover {
    background-color: var(--color-red-700);
  }
  .hover\\:bg-red-800:hover {
    background-color: var(--color-red-800);
  }
  .hover\\:bg-red-900:hover {
    background-color: var(--color-red-900);
  }
  .hover\\:bg-red-950:hover {
    background-color: var(--color-red-950);
  }
}

```

This feature is also compatible with the `not` keyword that we're about
to add to `@source "…"` in a follow-up PR. This can be used to set up an
ignore list purely in CSS. The following code snippet, for example, will
ensure that the `.container` utility is never created:

```css
@theme {
  --breakpoint-sm: 40rem;
  --breakpoint-md: 48rem;
  --breakpoint-lg: 64rem;
  --breakpoint-xl: 80rem;
  --breakpoint-2xl: 96rem;
}
@source not inline("container");
@tailwind utilities;
```

## Test plan

- See added unit tests
- The new brace expansion library was also benchmarked against the
popular `braces` library:
  ```
  clk: ~3.96 GHz
  cpu: Apple M4 Max
  runtime: bun 1.1.34 (arm64-darwin)

benchmark avg (min … max) p75 / p99 (min … top 1%)
-------------------------------------------
-------------------------------
braces 31.05 ms/iter 32.35 ms █ █
(28.14 ms … 36.35 ms) 35.14 ms ██ █
( 0.00 b … 116.45 mb) 18.71 mb ██████▁▁▁██▁█▁██▁█▁▁█

./brace-expansion 19.34 ms/iter 21.69 ms █
(12.53 ms … 26.63 ms) 25.53 ms ▅ ▅ █ █
( 0.00 b … 114.13 mb) 11.86 mb █▁▅▁██▁▅█▅█▅▁█▅█▅▅▁▅█

┌ ┐
╷┌────┬─┐ ╷
braces ├┤ │ ├─────┤
╵└────┴─┘ ╵
                              ╷        ┌────┬───┐       ╷
            ./brace-expansion ├────────┤    │   ├───────┤
                              ╵        └────┴───┘       ╵
└ ┘
12.53 ms 23.84 ms 35.14 ms
  ```

---------

Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
2025-03-12 13:55:33 +00:00
Robin Malfait
4455048c0b
Prepare release 4.0.13 (#17132) 2025-03-11 17:58:53 +01:00
Robin Malfait
2f28e5fbcb
Prepare v4.0.12 release (#17033)
Co-authored-by: Philipp Spiess <hello@philippspiess.com>
2025-03-07 12:38:53 +01:00
Philipp Spiess
225f3233b6
Enable URL rewriting for PostCSS (#16965)
Fixes #16636 

This PR enables URL rebasing for PostCSS. Furthermore it fixes an issue
where transitive imports rebased against the importer CSS file instead
of the input CSS file. While fixing this we noticed that this is also
broken in Vite right now and that our integration test swallowed that
when testing because it did not import any Tailwind CSS code and thus
was not considered a Tailwind file.

## Test plan

- Added regression integration tests
- Also validated it against the repro of
https://github.com/tailwindlabs/tailwindcss/issues/16962:
  
<img width="1149" alt="Screenshot 2025-03-05 at 16 41 01"
src="https://github.com/user-attachments/assets/85396659-d3d0-48c0-b1c7-6125ff8e73ac"
/>

---------

Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
Co-authored-by: Jordan Pittman <jordan@cryptica.me>
2025-03-07 12:18:10 +01:00
depfu[bot]
bd1e540776
Update h3 1.15.0 → 1.15.1 (patch) (#17010) 2025-03-07 12:00:44 +01:00
Philipp Spiess
3d0606b82d
Fix sorting of classes that have undefined declarations (#16995)
Closes #16973

Declaration values of `undefined` are an implementation detail and
skipped when printing the CSS. Thus, these should not count towards the
sort order at a..

## Test plan

- See added regression test
2025-03-06 15:20:12 +01:00
Philipp Spiess
b676da8ace
Prepare v4.0.11 release (#16987) 2025-03-06 11:09:39 +00:00
Philipp Spiess
1638b16fee
Prepare v4.0.10 release (#16963)
Co-authored-by: Adam Wathan <adam.wathan@gmail.com>
2025-03-05 18:32:15 +01:00
Philipp Spiess
a8b64f3465
Vite: Work around crash when .svg file contains # or ? (#16957)
Closes #16877

This PR works around #16877 by not registering `.svg` files containing a
`#` or `?` as a watch dependency for now.

## Test plan

- Add a file to the Vite playground called `src/c#.svg`
- Observe Vite no longer prints errors
2025-03-05 14:55:07 +01:00
depfu[bot]
0b36dd51c3
Update @types/bun 1.2.3 → 1.2.4 (patch) (#16955) 2025-03-05 12:30:46 +00:00
Philipp Spiess
1c2ad57f03
Add pointer-* variants (#16946)
Adds new variants under a feature flag:

- `pointer-none`
- `pointer-coarse`
- `pointer-fine`
- `any-pointer-none`
- `any-pointer-coarse`
- `any-pointer-fine`
2025-03-05 11:05:17 +00:00
Philipp Spiess
2eecb4d0b6
Remove max-w-auto and max-h-auto (#16917)
Closes #16916

This PR removes `max-w-auto` and `max-h-auto` due to them not being part
of v3 and not being valid CSS:

- https://developer.mozilla.org/en-US/docs/Web/CSS/max-width#syntax
- https://developer.mozilla.org/en-US/docs/Web/CSS/max-height#syntax

<img width="886" alt="Screenshot 2025-03-03 at 14 00 39"
src="https://github.com/user-attachments/assets/2c7fa17c-975b-4e1f-ae56-99b703d6ca70"
/>

<img width="163" alt="Screenshot 2025-03-03 at 13 54 26"
src="https://github.com/user-attachments/assets/12902a14-5a1e-4d7f-8127-fc2a3833221d"
/>

I decided to keep `max-w-auto` and `max-h-auto` since these values are
valid even though these were not in v3 either:

<img width="886" alt="Screenshot 2025-03-03 at 13 55 11"
src="https://github.com/user-attachments/assets/83bf6543-06a3-429e-b39e-ef3ac3290f0b"
/>
2025-03-05 11:59:33 +01:00
depfu[bot]
13acd24830
Update bun 1.2.3 → 1.2.4 (patch) (#16954) 2025-03-05 11:56:50 +01:00
Robin Malfait
57b080c5f2
Allow !important on CSS variables (#16873)
We recently fixed an issue
(https://github.com/tailwindlabs/tailwindcss/issues/16664) so that we
could remove the `!important` on CSS variables. The reason we did that
is because Google Chrome is showing a warning in the devtools styles
panel that this is invalid. However, this _is_ valid and the code
actually works as expected.

If we look at the CSS spec for this:

> Note: Custom properties can contain a trailing `!important`, but this
is automatically removed from the property’s value by the CSS parser,
and makes the custom property "important" in the CSS cascade. In other
words, the prohibition on top-level "!" characters does not prevent
`!important` from being used, as the `!important` is removed before
syntax checking happens.
>
> — https://www.w3.org/TR/css-variables-1/#syntax


So given this input:
```css
@import "tailwindcss";

body {
  --text-color: var(--color-white) !important;
  --bg-color: var(--color-blue-950) !important;

  /* Direct usage */
  background-color: var(--bg-color);

  /* Usage inside other functions as-if the `!important` is in the middle instead of the end */
  color: color-mix(in oklab, var(--text-color) 75%, transparent);
}
```

You will notice that everything works as expected, but if you look at
the Styles panel in Chrome for the `<body>` element, you will see an
incorrect warning. (At least that's what you used to see, I updated
Chrome and everything renders fine in devtools).

Play: https://play.tailwindcss.com/BpjAJ6Uxg3?file=css

This change reverts the "fix" for:
https://github.com/tailwindlabs/tailwindcss/issues/16664. @winchesHe you
were the original person that opened the issue so this info might be
useful to you as well. Can you verify that the Play link above does work
as expected for you?

Fixes: #16810
2025-03-04 16:21:56 +00:00
Philipp Spiess
db405304f4
Don't swallow @utility declarations when @apply is used in nested rules (#16940)
Fixes #16935

This PR fixes an issue where the order of how `@apply` was resolved was
incorrect for nested rules. Consider this example:

```css
.rule {
  @apply underline;
  .nested-rule {
    @apply custom-utility;
  }
}

@utility custom-utility {
  @apply flex;
}
```

The way we topologically sort these, we end up with a list that looks
roughly like this:

```css
.rule {
  @apply underline;
  .nested-rule {
    @apply custom-utility;
  }
}

@utility custom-utility {
  @apply flex;
}

.nested-rule {
  @apply custom-utility;
}
```

As you can see here the nested rule is now part of the top-level list.
This is correct because we first have to substitute the `@apply` inside
the `@utility custom-utility` before we can apply the `custom-utility`
inside `.nested-rule`. However, because we were using a regular AST walk
and because the initial `.rule` also contains the `.nested-rule` as
child, we would first substitute the `@apply` inside the `.nested-rule`,
causing the design-system to force resolve (and cache) the wrong value
for `custom-utility`.

Because the list is already flattened, we do not need to recursively
look into child declarations when we traverse the sorted list. This PR
changes it to use a regular `for` loop instead of the `walk`.

## Test plan

- Added a regression test
- Rest of tests still green
2025-03-04 16:54:05 +01:00
Philipp Spiess
b0aa20c30e
Ensure outline-hidden behaves like outline-none in non-forced-colors mode (#16943)
Part-of #16926

I noticed that `outline-hidden` would not set `--tw-outline-style`
(contrary to `outline-none`), thus stacking it with other outline
classes won't work as expected: https://play.tailwindcss.com/Y0lPGgekYh
2025-03-04 16:36:28 +01:00
Adam Wathan
595b88f271
Support bare col-* and row-* utilities (#15183)
Resolves #15170.

This PR adds support for bare integer values to the `col-*` and `row-*`
utilities:

```css
.col-5 {
  grid-column: 5;
}
.row-6 {
  grid-row: 6;
}
```

These properties are shorthands for
`grid-column-start`/`grid-column-end` and
`grid-row-start`/`grid-row-end`, so using a bare integer value ends up
being a shortcut for:

```css
.col-5 {
  grid-column-start: 5;
  grid-column-end: auto;
}
```

…which makes these basically work like an alternative to `col-start-*`
and `row-start-*`.

These support negative values like `-col-6` as well, which also
technically extends to arbitrary values like `-col-[6/span_2]` now even
though that is a junk value. I've decided not to guard against that
though and just consider it user error to keep the implementation
simple.

---------

Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
Co-authored-by: Philipp Spiess <hello@philippspiess.com>
2025-02-27 23:58:24 +01:00
Philipp Spiess
66ef77ce76
Emit @keyframes in prefixed setup (#16850)
Closes #16829

We were only adding keyframes used in variables starting with
`--animate` (without adding a potential prefix).

## Test plan

- Added a unit test
2025-02-27 17:35:25 +01:00
Luke Warlow
5532d48e8e
Add scripting variants (#11929)
This adds two variants for the
[`scripting`](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/scripting)
media query. `noscript` for when JavaScript is disabled and `scripting`
for when it's enabled.

---------

Co-authored-by: Philipp Spiess <hello@philippspiess.com>
2025-02-26 18:43:24 +01:00
Philipp Spiess
e938c58778
Ensure not-* does not remove :is(…) (#16825)
Resolves #16821

This PR removes a special case in the `not-*` variant compound that
removed `:is(…)` if it was the only part of the inversed selector list.
While in-theory this makes sense, `:is(…)` accepts a _forgiving_
selector list where as `:not(…)` does not. See the [last point
here](https://developer.mozilla.org/en-US/docs/Web/CSS/:not#description).

This is an issue specifically in combinations with variants that have
selectors that are not supported by all browsers yet, for example
`:open`.

It seems to be the most expected to simply keep the `:is(…)` here in any
case.

## Test plan
- Ensured the repro form #16821 now also works in browsers that do not
support `:open` (Safari and Firefox at the time of writing this):
<img width="484" alt="Screenshot 2025-02-26 at 15 36 22"
src="https://github.com/user-attachments/assets/f3391693-895b-4e44-8566-95e2960ec4e3"
/>
2025-02-26 18:03:11 +01:00