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
```
Turns out all of these date/time pseudo elements have a bit of
horizontal padding on them that we don't want to throw away when fixing
the height issue, so this PR updates our reset to only remove vertical
padding.
Here's a demo showing the difference, test in Safari or Chrome to see
the difference in horizontal spacing:
https://play.tailwindcss.com/Opwa7pkDFP?file=css
---------
Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
This PR updates our default `theme.css` file and organizes the CSS
variables in a custom order that's optimized for looking nice in Chrome
dev tools.
You can only see ~50 variables "above the fold" in dev tools without
clicking "Show all", so I've opted for putting variables near the top
that have the highest "impact" on the design/brand of the site, and also
showcase some of the modern CSS features we are using in Tailwind CSS
v4.
Here's what it looks like:
<kbd><img width="957" alt="image"
src="https://github.com/user-attachments/assets/dade9244-6e22-4822-ac5c-ffa33e895f6e"></kbd>
I really want to show off the color palette because the swatches look
nice and because seeing `oklch` there feels like a nice signal for
Tailwind CSS v4 being very modern, but we have a lot of colors so you
can't really fit much else if you do this. I stuck font families at the
top since it's one of the few things that we can fit there that also
feels important to your site's brand but still has few enough values not
to push away the color palette.
Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
This PR removes the `--leading-none` variable from the default theme in
favor of making `leading-none` a static utility, since it doesn't make
sense to change the value of this on a per-project basis. This is
consistent with how `none` values work for other utilities in the
framework.
Some folks in the past have wanted `leading-none` to be `line-height: 0`
but technically "leading" is the space between lines, and `line-height:
1` removes all extra space between lines so it feels correct to me
(although it means all of the numeric utilities like `leading-6` are not
technically correct but I try hard not to think about that too much).
If someone wants `line-height: 0` they can use `leading-0` in v4 since
the `leading-*` utilities inherit the spacing scale now.
---------
Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
This PR deprecates the `shadow-inner` value in favor of
`inset-shadow-sm` which does the same thing but is composable with other
outer shadows.
It's still included in the default theme but is registered as `inline
reference` and doesn't add any CSS variables to the output.
---------
Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
This PR adds some additional styles to Preflight to normalize a bunch of
inconsistencies in date/time inputs across browsers.
The main motivation for this is to remove these insane classes we have
to add in Catalyst:
```html
<input type="date" class="[&::-webkit-datetime-edit-fields-wrapper]:p-0 [&::-webkit-date-and-time-value]:min-h-[1.5em]
[&::-webkit-datetime-edit]:inline-flex [&::-webkit-datetime-edit]:p-0 [&::-webkit-datetime-edit-year-field]:p-0
[&::-webkit-datetime-edit-month-field]:p-0 [&::-webkit-datetime-edit-day-field]:p-0
[&::-webkit-datetime-edit-hour-field]:p-0 [&::-webkit-datetime-edit-minute-field]:p-0
[&::-webkit-datetime-edit-second-field]:p-0 [&::-webkit-datetime-edit-millisecond-field]:p-0
[&::-webkit-datetime-edit-meridiem-field]:p-0"/>
```
With these normalizations, changing things like padding, display type,
etc. gives consistent results (at least as consistent as is actually
possible) across all browsers.
---
**Make text alignment work on iOS Safari**
<kbd><img width="418" alt="iOS Safari text alignment"
src="https://github.com/user-attachments/assets/0ff792b2-1f3a-40c6-9185-6bd076c8715d"></kbd>
---
**Don't shrink date inputs on iOS Safari when there is no selected
value**
<kbd><img width="409" alt="ioS Safari no input"
src="https://github.com/user-attachments/assets/a8e69af7-3f0c-4d1d-b7a0-10355a5d3907"></kbd>
---
**Fix padding in macOS Safari**
<kbd><img width="717" alt="MacOS Safari"
src="https://github.com/user-attachments/assets/5ea19b66-2dec-46e2-a386-d61bd5b8517a"></kbd>
---------
Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
This PR reverts a change we made for v4 that added borders to inputs by
default. It feels like we have to go further than this for this to
actually be useful to anyone, and since there were no borders in v3 it's
also a breaking change.
If we wanted to make form elements look more "normal" out of the box I
think we need to do something more like this:
https://play.tailwindcss.com/icCwFLVp4z?file=css
But it's a huge rabbit hole and there are so many stupid details to get
right that it feels like an insurmountable task, and if we can't go all
the way with it it's better to just maximize compatibility with v3.
---------
Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
Part of the current changes, we also want to make the `--line-height-*`
namespace closer to the utility name so we're renaming it to
`--leading-*`:
```diff
@theme {
- --line-height-none: 1;
- --line-height-tight: 1.25;
- --line-height-snug: 1.375;
- --line-height-normal: 1.5;
- --line-height-relaxed: 1.625;
- --line-height-loose: 2;
/* ... */
+ --leading-none: 1;
+ --leading-tight: 1.25;
+ --leading-snug: 1.375;
+ --leading-normal: 1.5;
+ --leading-relaxed: 1.625;
+ --leading-loose: 2;
/* ... */
}
```
Notice that we did not change the nested values used in the `--text`
type scale, e.g.:
```css
@theme {
/* Type scale */
--text-xs: 0.75rem;
--text-xs--line-height: 1rem;
}
```
These do not refer to the `leading` utility and instead refer to nested
properties so we're keeping those as-is.
## Test Plan
Added cases to the CSS `theme()` variable/JS plugin tests (interop
layer) and the integration tests (codemod layer).
Part of the current changes, we also want to make the
`--letter-spacing-*` namespace closer to the utility name so we're
renaming it to `--tracking-*`:
```diff
@theme {
- --letter-spacing-tighter: -0.05em;
- --letter-spacing-tight: -0.025em;
- --letter-spacing-normal: 0em;
- --letter-spacing-wide: 0.025em;
- --letter-spacing-wider: 0.05em;
- --letter-spacing-widest: 0.1em;
/* ... */
+ --tracking-tighter: -0.05em;
+ --tracking-tight: -0.025em;
+ --tracking-normal: 0em;
+ --tracking-wide: 0.025em;
+ --tracking-wider: 0.05em;
+ --tracking-widest: 0.1em;
/* ... */
}
```
## Test Plan
Added cases to the CSS `theme()` variable/JS plugin tests (interop
layer) and the integration tests (codemod layer).
Early in v4 development we decided to give all form controls a
transparent background, but in v3 we only did this for button elements.
This PR reverts that decision to make things consistent with v3, as
we've noticed this is something that tends to break for people when
upgrading from v3 to v4.
The default background color of form elements is the [`Field` system
color](https://developer.mozilla.org/en-US/docs/Web/CSS/system-color#field)
which automatically adapts to light and dark modes if you don't touch
it, so it feels reasonable to keep this as the default. Changing it just
makes upgrading harder and doesn't really make anything easier for
anyone else.
---------
Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
This PR updates all of the `--font-size-*` variables to `--text-*`
instead to closer match the utility names.
```diff
@theme {
- --font-size-xs: 0.75rem;
- --font-size-xs--line-height: 1rem;
- --font-size-sm: 0.875rem;
- --font-size-sm--line-height: 1.25rem;
- --font-size-base: 1rem;
- --font-size-base--line-height: 1.5rem;
- --font-size-lg: 1.125rem;
- --font-size-lg--line-height: 1.75rem;
- --font-size-xl: 1.25rem;
- --font-size-xl--line-height: 1.75rem;
/* ... */
+ --text-xs: 0.75rem;
+ --text-xs--line-height: 1rem;
+ --text-sm: 0.875rem;
+ --text-sm--line-height: 1.25rem;
+ --text-base: 1rem;
+ --text-base--line-height: 1.5rem;
+ --text-lg: 1.125rem;
+ --text-lg--line-height: 1.75rem;
+ --text-xl: 1.25rem;
+ --text-xl--line-height: 1.75rem;
/* ... */
}
```
This is part of a bigger set of changes where we're renaming other theme
variables as well with the same goals, since many existing theme
variables like `--shadow-*` and `--radius-*` are already not using the
explicit CSS property name.
---------
Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
Co-authored-by: Philipp Spiess <hello@philippspiess.com>
Co-authored-by: Jordan Pittman <jordan@cryptica.me>
This PR renames all of the `--width-*` variables to `--container-*` to
better communicate the purpose of these tokens as layout container
sizes. These are the values that were historically stored under
`maxWidth` in the v3 and earlier eras, and were also re-used by the
container queries plugin.
The name `--container-*` feels like a better match alongside the
`--breakpoint-*` namespace and since these both serve that same sort of
purpose it makes sense to me that the name should be optimized for
feeling "right" in that context.
I like that this also sort of advertises Tailwind's support for
container queries directly in the CSS variables themselves, and helps
people understand what these are really intended to be used for.
---------
Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
This PR renames the `--transition-timing-function-*` theme variables to
`--ease-*` to more closely match the utility names and be a bit more
terse in general.
```diff
@theme {
- --transition-timing-function-in: cubic-bezier(0.4, 0, 1, 1);
- --transition-timing-function-out: cubic-bezier(0, 0, 0.2, 1);
- --transition-timing-function-in-out: cubic-bezier(0.4, 0, 0.2, 1);
+ --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);
}
```
This is part of a bigger set of changes where we're renaming other theme
variables as well with the same goals, since many existing theme
variables like `--shadow-*` and `--radius-*` are already not using the
explicit CSS property name.
---------
Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
This PR renames the `--font-family-*` theme variables to `--font-*` to
more closely match the utility names and be a bit more terse in general.
```diff
@theme {
- --font-family-sans: ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
- --font-family-serif: ui-serif, Georgia, Cambria, 'Times New Roman', Times, serif;
- --font-family-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;
+ --font-sans: ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
+ --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;
}
```
This is part of a bigger set of changes where we're renaming other theme
variables as well with the same goals, since many existing theme
variables like `--shadow-*` and `--radius-*` are already not using the
explicit CSS property name.
---------
Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
This PR improves the generated CSS by running it through Lightning CSS
twice.Right now Lightning CSS merges adjacent at-rules and at the end
flattens the nesting. This means that after the nesting is flattened,
the at-rules that are adjacent and could be merged together will not be
merged.
This PR improves our output by running Lightning CSS twice on the
generated CSS which will make sure to merge adjacent at-rules after the
nesting is flattened.
Note: in the diff output you'll notice that some properties are
duplicated. These need some fixes in Lightning CSS itself but they don't
break anything for us right now.
Related PR in Lightning CSS for the double `-webkit-backdrop-filter` can
be found here: https://github.com/parcel-bundler/lightningcss/pull/850
---------
Co-authored-by: Philipp Spiess <hello@philippspiess.com>
This PR removes all of the static `font-weight` utilities that were
previously hard-coded into the framework in favor of deriving those
utilities from the `--font-weight-*` theme values instead.
Biggest motivation for this is giving people a way to explicitly disable
font-weight utilities they don't want to use in their project, which
previously wasn't possible.
---------
Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
This PR changes how we render `var(...)` calls for theme values,
removing the fallback values we were previously including.
```diff
.text-white {
- color: var(--color-white, #fff);
+ color: var(--color-white);
}
```
We previously included the fallbacks only so you could see the value in
dev tools but this feels like a bad reason to bloat the CSS. I'd rather
just convince the Chrome team to surface this stuff better in dev tools
in the first place.
---------
Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
This PR replaces the default spacing scale (`--spacing-*`) with a
generative system based on a default spacing _unit_.
Instead of the default theme containing values like `--spacing-4`,
`--spacing-6`, `--spacing-8`, etc., instead we just define a single
`--spacing` value:
```css
@theme {
--spacing: 0.25rem;
}
```
Utilities like `px-4` are derived from this unit by multiplying it by
the value in the utility (4 in this case):
```css
.px-4 {
padding-inline: calc(var(--spacing) * 4);
}
```
The biggest consequence of this change is that every value is available
now, rather than just the explicitly configured values.
This means utilities like `px-42` will work now, whereas prior to this
PR only `px-40` and `px-44` were valid utilities. I personally found it
very difficult to know which values actually existed at the higher end
of the scale without IntelliSense, and in practice even when working
with a skilled designer like [Steve](https://x.com/steveschoger) who
helped design Tailwind's default spacing scale, I'd very often need to
break out of it to implement a design, and trying to round to a value
that was in the scale made the design worse, not better.
This PR allows you to use any whole number, as well as decimal numbers
that are multiples of `0.25` to ensure classes like `px-1.5` continue to
work. While this means you can now technically do things like
`pt-97.25`, I think the presence of the fractional value will be enough
of a signal to developers that they are doing something a little
unusual, and they can use their judgment as to whether they are making
the right decision or not.
I'll update this PR with a lot more detail when I have a chance, as
there are a few other things to explain like:
- Unifying all of the values for
width/min-width/max-width/height/min-height/max-height utilities
- Deriving numeric line-height values from the spacing multiplier
instead of a separate line-height scale
- Using `--spacing: initial` to disable the multiplier
- How you can still use an explicit spacing scale and ignore this change
- How we plan to use IntelliSense to surface a more curated set of
spacing values even if smaller increments work when you type them
explicitly
---------
Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
This PR removes `--transition-timing-function-linear` from the default
theme in favor of a static `ease-linear` utility. Doesn't make sense for
this to be a design token since `linear` can only mean `linear`.
This is consistent with how we handle basically every other similar case
in the framework.
---------
Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
This PR reworks the default `--shadow-*` and `--inset-shadow-*` scales
to remove the bare `shadow` and `inset-shadow` utilities, and ensure
every shadow has an explicit size as part of the utility name.
Here's a complete list of changes:
| v3 | v4 Alpha | Proposed |
| ----------------- | ----------------- | ------------------ |
| _N/A_ | `shadow-xs` | `shadow-2xs` |
| `shadow-sm` | `shadow-sm` | `shadow-xs` |
| `shadow` | `shadow` | `shadow-sm` |
| `shadow-md` | `shadow-md` | `shadow-md` |
| `shadow-lg` | `shadow-lg` | `shadow-lg` |
| `shadow-xl` | `shadow-xl` | `shadow-xl` |
| _N/A_ | `inset-shadow-xs` | `inset-shadow-2xs` |
| _N/A_ | `inset-shadow-sm` | `inset-shadow-xs` |
| `shadow-inner` | `inset-shadow` | `inset-shadow-sm` |
The motivation for this change is just to make the scale more
predictable — it's never been intuitive to me that `shadow` sits in
between `shadow-sm` and `shadow-md`.
This PR doesn't remove the ability to create classes like `shadow` and
`inset-shadow` by adding bare `--shadow` and `--inset-shadow` theme
variables, but does remove them from the default theme.
## Impact
We'll include a codemod for this in our upgrade tool to automate this
change for people upgrading from v3 to v4, but this is still sort of an
annoying breaking change admittedly and will make lots of educational
resources, example components, and LLM tools out of date for v4 😕 At the
same time I don't want to feel like we can never correct regrettable
legacy decisions just to preserve backward compatibility.
We made a similar change like this when we went from the v0.x color
palette to the v1.x color palette changing names like `bg-red` to
`bg-red-500` and that proved to definitely be the right decision long
term, so want to rip the band-aid off here too if we can.
Planning to make the same change for `rounded`, `drop-shadow`, and
`blur` as well — maybe in separate PRs but maybe just all in this one as
well since I don't think we want to do one and not all.
_Update_: I've also made the same changes to the `--radius-*`,
`--drop-shadow-*`, and `--blur-*` scales now, effectively removed the
`rounded`, `drop-shadow`, and `blur` classes by default, and changing
the meaning `rounded-sm`, `drop-shadow-sm`, and `blur-sm`.
We'll put together a codemod to handle this stuff in a separate PR.
---------
Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
When migrating a project from Tailwind CSS v3 to Tailwind CSS v4, then
we started the migration process in the following order:
1. Migrate the JS/TS config file
2. Migrate the source files (found via the `content` option)
3. Migrate the CSS files
However, if you have a setup where you have multiple CSS root files
(e.g.: `frontend` and `admin` are separated), then that typically means
that you have an `@config` directive in your CSS files. These point to
the Tailwind CSS config file.
This PR changes the migration order to do the following:
1. Build a tree of all the CSS files
2. For each `@config` directive, migrate the JS/TS config file
3. For each JS/TS config file, migrate the source files
If a CSS file does not contain any `@config` directives, then we start
by filling in the `@config` directive with the default Tailwind CSS
config file (if found, or the one passed in). If no default config file
or passed in config file can be found, then we will error out (just like
we do now)
---------
Co-authored-by: Adam Wathan <adam.wathan@gmail.com>
This PR removes `--drop-shadow-none` from the default theme which
shouldn't ever have been there since we handle all `*-none` utilities as
static/permanent utilities in the framework now.
I've added `drop-shadow-none` as an explicit static utility, and also
slightly improved test coverage for `getClassList` around drop shadows
while touching this part of the code.
---------
Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
This PR introduces a new `source(…)` argument and improves on the
existing `@source`. The goal of this PR is to make the automatic source
detection configurable, let's dig in.
By default, we will perform automatic source detection starting at the
current working directory. Auto source detection will find plain text
files (no binaries, images, ...) and will ignore git-ignored files.
If you want to start from a different directory, you can use the new
`source(…)` next to the `@import "tailwindcss/utilities"
layer(utilities) source(…)`.
E.g.:
```css
/* ./src/styles/index.css */
@import 'tailwindcss/utilities' layer(utilities) source('../../');
```
Most people won't split their source files, and will just use the simple
`@import "tailwindcss";`, because of this reason, you can use
`source(…)` on the import as well:
E.g.:
```css
/* ./src/styles/index.css */
@import 'tailwindcss' source('../../');
```
Sometimes, you want to rely on auto source detection, but also want to
look in another directory for source files. In this case, yuo can use
the `@source` directive:
```css
/* ./src/index.css */
@import 'tailwindcss';
/* Look for `blade.php` files in `../resources/views` */
@source '../resources/views/**/*.blade.php';
```
However, you don't need to specify the extension, instead you can just
point the directory and all the same automatic source detection rules
will apply.
```css
/* ./src/index.css */
@import 'tailwindcss';
@source '../resources/views';
```
If, for whatever reason, you want to disable the default source
detection feature entirely, and only want to rely on very specific glob
patterns you define, then you can disable it via `source(none)`.
```css
/* Completely disable the default auto source detection */
@import 'tailwindcss' source(none);
/* Only look at .blade.php files, nothing else */
@source "../resources/views/**/*.blade.php";
```
Note: even with `source(none)`, if your `@source` points to a directory,
then auto source detection will still be performed in that directory. If
you don't want that, then you can simply add explicit files in the globs
as seen in the previous example.
```css
/* Completely disable the default auto source detection */
@import 'tailwindcss' source(none);
/* Run auto source detection in `../resources/views` */
@source "../resources/views";
```
---------
Co-authored-by: Jordan Pittman <jordan@cryptica.me>
Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
This PR adds `postcss` as a dependency of `@tailwindcss/postcss`.
If you are in an environment with Next.js where you can use the
`@tailwindcss/postcss` package, then `postcss` is required.
If you have `postcss` in your `package.json`, then everything is fine,
however if you don't then you will get an error that `postcss` cannot be
found.
Note: this only happens when you are using `npm`, if you are using
`pnpm`, then the `postcss` package can be resolved correctly and you
won't run into issues. This is also why the integration tests just
worked (because we use `pnpm`).
To make sure that this package works for most people in most
environments, we explicitly add `postcss` as a dependency of
`@tailwindcss/postcss`.
---
I wanted to create an integration test for this to make sure this works,
but we are currently using `pnpm` with some of `pnpm`'s features to make
sure that we can override dependencies that point to `.tgz` files.
This PR updates all of our OKCLH colors to use `0` instead of `none` due
to weird behavior in Chrome where using `color-mix` with colors using
`none` produces unexpected results:
<img width="1110" alt="image"
src="https://github.com/user-attachments/assets/2272e494-500b-4f75-b5c1-d41c714f0339">
Both `none` and `0` behave as expected in Safari and Firefox so
suspecting this is a bug in Chrome rather than spec'd behavior.
Fixes#14740
---------
Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
This PR updates all of the colors in our default theme to use OKLCH
instead of RGB and increases the overall chroma to take advantage of the
wider color gamut.
Just a first draft based on @danhollick's initial work — expecting these
will be further refined before a stable release as we continue to test
them.
<img width="628" alt="image"
src="https://github.com/user-attachments/assets/2de1bfca-fddd-47f9-b609-39f26abdee41">
---------
Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
Fixes an issue reported by the React Aria Components team here:
https://github.com/adobe/react-spectrum/issues/7160
Basically `hidden="until-found"` behaves very differently than `hidden`
and doesn't actually use `display: none`, so we don't want to apply the
behavior we apply for the regular `hidden` attribute.
This PR improves the performance of the `@tailwindcss/postcss` plugin.
Before this change we created 2 compiler instances instead of a single
one. On a project where a `tailwindcss.config.ts` file is used, this
means that the timings look like this:
```
[@tailwindcss/postcss] Setup compiler: 137.525ms
⋮
[@tailwindcss/postcss] Setup compiler: 43.95ms
```
This means that with this small change, we can easily shave of ~50ms for
initial PostCSS builds.
---------
Co-authored-by: Philipp Spiess <hello@philippspiess.com>
Co-authored-by: Jordan Pittman <jordan@cryptica.me>
This PR exposes when using the the `DEBUG` environment variable. This
follows the `DEBUG` conventions where:
- `DEBUG=1`
- `DEBUG=true`
- `DEBUG=*`
- `DEBUG=tailwindcss`
Will enable the debug information, but when using:
- `DEBUG=0`
- `DEBUG=false`
- `DEBUG=-tailwindcss`
It will not.
This currently only exposes some timings related to:
1. Scanning for candidates
2. Building the CSS
3. Optimizing the CSS
We can implement a more advanced version of this where we also expose
more fine grained information such as the files we scanned, the amount
of candidates we found and so on. But I believe that this will be enough
to start triaging performance related issues.
This PR brings `@import` resolution into Tailwind CSS core. This means
that our clients (PostCSS, Vite, and CLI) no longer need to depend on
`postcss` and `postcss-import` to resolve `@import`. Furthermore this
simplifies the handling of relative paths for `@source`, `@plugin`, or
`@config` in transitive CSS files (where the relative root should always
be relative to the CSS file that contains the directive). This PR also
fixes a plugin resolution bug where non-relative imports (e.g. directly
importing node modules like `@plugin '@tailwindcss/typography';`) would
not work in CSS files that are based in a different npm package.
### Resolving `@import`
The core of the `@import` resolution is inside
`packages/tailwindcss/src/at-import.ts`. There, to keep things
performant, we do a two-step process to resolve imports. Imagine the
following input CSS file:
```css
@import "tailwindcss/theme.css";
@import "tailwindcss/utilities.css";
```
Since our AST walks are synchronous, we will do a first traversal where
we start a loading request for each `@import` directive. Once all loads
are started, we will await the promise and do a second walk where we
actually replace the AST nodes with their resolved stylesheets. All of
this is recursive, so that `@import`-ed files can again `@import` other
files.
The core `@import` resolver also includes extensive test cases for
[various combinations of media query and supports conditionals as well
als layered
imports](https://developer.mozilla.org/en-US/docs/Web/CSS/@import).
When the same file is imported multiple times, the AST nodes are
duplicated but duplicate I/O is avoided on a per-file basis, so this
will only load one file, but include the `@theme` rules twice:
```css
@import "tailwindcss/theme.css";
@import "tailwindcss/theme.css";
```
### Adding a new `context` node to the AST
One limitation we had when working with the `postcss-import` plugin was
the need to do an additional traversal to rewrite relative `@source`,
`@plugin`, and `@config` directives. This was needed because we want
these paths to be relative to the CSS file that defines the directive
but when flattening a CSS file, this information is no longer part of
the stringifed CSS representation. We worked around this by rewriting
the content of these directives to be relative to the input CSS file,
which resulted in added complexity and caused a lot of issues with
Windows paths in the beginning.
Now that we are doing the `@import` resolution in core, we can use a
different data structure to persist this information. This PR adds a new
`context` node so that we can store arbitrary context like this inside
the Ast directly. This allows us to share information with the sub tree
_while doing the Ast walk_.
Here's an example of how the new `context` node can be used to share
information with subtrees:
```ts
const ast = [
rule('.foo', [decl('color', 'red')]),
context({ value: 'a' }, [
rule('.bar', [
decl('color', 'blue'),
context({ value: 'b' }, [
rule('.baz', [decl('color', 'green')]),
]),
]),
]),
]
walk(ast, (node, { context }) => {
if (node.kind !== 'declaration') return
switch (node.value) {
case 'red': assert(context.value === undefined)
case 'blue': assert(context.value === 'a')
case 'green': assert(context.value === 'b')
}
})
```
In core, we use this new Ast node specifically to persist the `base`
path of the current CSS file. We put the input CSS file `base` at the
root of the Ast and then overwrite the `base` on every `@import`
substitution.
### Removing the dependency on `postcss-import`
Now that we support `@import` resolution in core, our clients no longer
need a dependency on `postcss-import`. Furthermore, most dependencies
also don't need to know about `postcss` at all anymore (except the
PostCSS client, of course!).
This also means that our workaround for rewriting `@source`, the
`postcss-fix-relative-paths` plugin, can now go away as a shared
dependency between all of our clients. Note that we still have it for
the PostCSS plugin only, where it's possible that users already have
`postcss-import` running _before_ the `@tailwindcss/postcss` plugin.
Here's an example of the changes to the dependencies for our Vite client
✨ :
<img width="854" alt="Screenshot 2024-09-19 at 16 59 45"
src="https://github.com/user-attachments/assets/ae1f9d5f-d93a-4de9-9244-61af3aff1237">
### Performance
Since our Vite and CLI clients now no longer need to use `postcss` at
all, we have also measured a significant improvement to the initial
build times. For a small test setup that contains only a hand full of
files (nothing super-complex), we measured an improvement in the
**3.5x** range:
<img width="1334" alt="Screenshot 2024-09-19 at 14 52 49"
src="https://github.com/user-attachments/assets/06071fb0-7f2a-4de6-8ec8-f202d2cc78e5">
The code for this is in the commit history if you want to reproduce the
results. The test was based on the Vite client.
### Caveats
One thing to note is that we previously relied on finding specific
symbols in the input CSS to _bail out of Tailwind processing
completely_. E.g. if a file does not contain a `@tailwind` or `@apply`
directive, it can never be a Tailwind file.
Since we no longer have a string representation of the flattened CSS
file, we can no longer do this check. However, the current
implementation was already inconsistent with differences on the allowed
symbol list between our clients. Ideally, Tailwind CSS should figure out
wether a CSS file is a Tailwind CSS file. This, however, is left as an
improvement for a future API since it goes hand-in-hand with our planned
API changes for the core `tailwindcss` package.
---------
Co-authored-by: Jordan Pittman <jordan@cryptica.me>
This PR improves how the `text-{size}` utilities interact with the
`leading-*`, `tracking-*`, and `font-{weight}` utilities, ensuring that
if the user explicitly uses any of those utilities that those values are
not squashed by any defaults baked into the `text-{size}` utilities.
Prior to this PR, if you wrote something like this:
```html
<div class="text-lg leading-none md:text-2xl">
```
…the `leading-none` class would be overridden by the default line-height
value baked into the `text-2xl` utility at the `md` breakpoint. This has
been a point of confusion and frustration for people [in the
past](https://github.com/tailwindlabs/tailwindcss/issues/6504) who are
annoyed they have to keep repeating their custom `leading-*` value like
this:
```html
<div class="text-lg leading-none md:text-2xl md:leading-none lg:text-4xl lg:leading-none">
```
This PR lets you write this HTML instead but get the same behavior as
above:
```html
<div class="text-lg leading-none md:text-2xl lg:text-4xl">
```
It's important to note that this change _only_ applies to line-height
values set explicitly with a `leading-*` utility, and does not apply to
the line-height modifier.
In this example, the line-height set by `text-sm/6` does _not_ override
the default line-height included in the `md:text-lg` utility:
```html
<div class="text-sm/6 md:text-lg">
```
That means these two code snippets behave differently:
```html
<div class="text-sm/6 md:text-lg">…</div>
<div class="text-sm leading-6 md:text-lg">…</div>
```
In the top one, the line-height `md:text-lg` overrides the line-height
set by `text-sm/6`, but in the bottom one, the explicit `leading-6`
utility takes precedence.
This PR applies the same improvements to `tracking-*` and
`font-{weight}` as well, since all font size utilities can also
optionally specify default `letter-spacing` and `font-weight` values.
We achieve this using new semi-private CSS variables like we do for
things like transforms, shadows, etc., which are set by the `leading-*`,
`tracking-*`, and `font-{weight}` utilities respectively. The
`text-{size}` utilities always use these values first if they are
defined, and the default values become fallbacks for those variables if
they aren't present.
We use `@property` to make sure these variables are reset to `initial`
on a per element basis so that they are never inherited, like with every
other variable we define.
This PR does slightly increase the amount of CSS generated, because now
utilities like `leading-5` look like this:
```diff
.leading-5 {
+ --tw-leading: 1.25rem;
line-height: 1.25rem;
}
```
…and utilites like `text-sm` include a `var(…)` lookup that they didn't
include before:
```diff
.text-sm {
font-size: 0.875rem;
- line-height: var(--font-size-sm--line-height, 1.25rem);
+ line-height: var(--tw-leading, var(--font-size-sm--line-height, 1.25rem));
}
```
If this extra CSS doesn't feel worth it for the small improvement in
behavior, we may consider just closing this PR and keeping things as
they are.
This PR is also a breaking change for anyone who was depending on the
old behavior, and expected the line-height baked into the `md:text-lg`
class to take precedence over the explicit `leading-6` class:
```html
<div class="text-sm leading-6 md:text-lg">…</div>
```
Personally I am comfortable with this because of the fact that you can
still get the old behavior by preferring a line-height modifier:
```html
<div class="text-sm/6 md:text-lg">…</div>
```
---------
Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
Co-authored-by: Jordan Pittman <jordan@cryptica.me>
When you configure custom content globs inside an `@config` file, we
want to tread these globs as being relative to that config file and not
the CSS file that requires the content file. A config can be used by
multiple CSS configs.
---------
Co-authored-by: Adam Wathan <adam.wathan@gmail.com>
<!--
👋 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>
In Tailwind v4 the CSS file is the main entry point to your project and
is generally configured via `@theme`. However, given that all v3
projects were configured via a `tailwind.config.js` file we definitely
need to support those. This PR adds support for loading existing
Tailwind config files by adding an `@config` directive to the CSS —
similar to how v3 supported multiple config files except that this is
now _required_ to use a config file.
You can load a config file like so:
```
@import "tailwindcss";
@config "./path/to/tailwind.config.js";
```
A few notes:
- Both CommonJS and ESM config files are supported (loaded directly via
`import()` in Node)
- This is not yet supported in Intellisense or Prettier — should
hopefully land next week
- TypeScript is **not yet** supported in the config file — this will be
handled in a future PR.
---------
Co-authored-by: Philipp Spiess <hello@philippspiess.com>
Co-authored-by: Adam Wathan <adam.wathan@gmail.com>
Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
Closes#14253
Since we changed the export strategy for the postcss client in #14132,
we accidentally no longer generated type exports for this package.
This PR adds a type export back. We now use a similar pattern to the
`./colors` and `./defaultTheme` exports in the tailwindcss package where
we have a separate cjs entrypoint.
The changes were validated manually in a playground project that were
installing the updated dependencies from tarballs.
Here is one example of it working as expected:
<img width="750" alt="Screenshot 2024-08-26 at 14 10 07"
src="https://github.com/user-attachments/assets/83de15f2-1543-4805-9231-9b8df1636c5e">