Personal notes.
Tailwind CSS v4.0 - Tailwind CSS
- New High-Performance Engine - Full builds are 5 times faster, and incremental builds are over 100 times faster — measured in microseconds.
- Designed for the Modern Web - Built on cutting-edge CSS features, registering custom properties using cascading layers,
@property
, andcolor-mix()
. - Simplified Installation - Fewer dependencies, zero configuration, just one line of code in your CSS file.
- First-Party Vite Plugin - Tightly integrated for maximum performance and minimal configuration.
- Automatic Content Detection - All template files are automatically discovered with no configuration needed.
- Built-in Import Support - Bundle multiple CSS files without extra tools.
- CSS-First Configuration - Redesigned developer experience where you can customize and extend the framework directly in CSS instead of a JavaScript configuration file.
- CSS Theme Variables - All your design tokens are exposed as native CSS variables, so you can access them anywhere.
- Dynamic Utility Values and Variants - No more guessing which values exist in spacing, and no more extending configuration for basic data attributes.
- Modernized P3 Color Palette - A redesigned, more vibrant palette that takes full advantage of modern display technology.
- Container Queries - Style elements based on container size using container queries, no plugins needed.
- New 3D Transform Utilities - Transform elements in 3D space directly in HTML, with added APIs for 3D transformations like
rotate-x-*
,rotate-y-*
,scale-z-*
,translate-z-*
, and more. - Expanded Gradient APIs - Radial and conic gradients, interpolation modes, etc. Now, linear gradients support angles as values, so you can create gradients at 45 degrees with utilities like
bg-linear-45
. Renamedbg-gradient-*
tobg-linear-*
. - @starting-style Support - The new
starting
variant adds support for the new CSS@starting-style
feature, allowing element properties to transition when the element first appears. - not-* Variant - Styles when an element does not match another variant, custom selector, or media or feature query.
- Even More New Utilities and Variants, including support for
color-scheme
,field-sizing
, complex shadows,inert
, and more.
More New Variants#
- New
inset-shadow-*
andinset-ring-*
Utilities - Allow stacking up to four layers of box shadows on one element. - New
field-sizing
Utility - For automated text columns without writing a single line of JavaScript.- Use
field-sizing-content
to allow form controls to resize based on content. - Use
field-sizing-fixed
for fixed sizes.
- Use
- New
color-scheme
- Reference CSS color scheme related colors using light-dark(). - New
font-stretch
Utility - For fine-tuning variable fonts that support different widths. - New
inert
Variant - Theinert
variant allows you to style elements marked with theinert
attribute, useful for adding visual cues to indicate that parts of the content are not interactive. - New
nth-*
Variants - Usenth-*
andnth-last-*
variants to style based on a child's position in a list, passing any number you want by default, and using arbitrary values for more complex expressions likenth-[2n+1_of_li]
. e.g.:nth-3:underline
nth-last-5:underline
nth-last-of-type-6:underline
.- For a complete list of available pseudo-class variants, see Pseudo-Class Reference.
- New
in-*
Variants - Very similar togroup-*
, but without thegroup
class.- The
in-*
variants respond to any parent's state changes, so if you want finer control, you need to usegroup
instead.
- The
- Support for
:popover-open
- Existingopen
style variants also target open popovers. - New Descendant Variants - For styling all descendant elements, good or bad.
- Like
*
, the**
variant can also be used to style an element's child elements. The main difference is that**
applies styles to all descendants, not just direct children. This is especially useful when combined with another variant to narrow down the selection.
- Like
Migration Notes#
For existing projects, we have released a comprehensive upgrade guide and built an automatic upgrade tool to help you use the latest version as quickly and painlessly as possible.
A small project to test the waters, executing the automated migration command.
npx @tailwindcss/upgrade@next
The migration output is as follows:
≈ tailwindcss v4.0.2
│ Searching for CSS files in the current directory and its subdirectories…
│ ↳ Linked `./tailwind.config.js` to `./src/styles/theme/shadcn.css`
│ Migrating JavaScript configuration files…
│ ↳ The configuration file at `./tailwind.config.js` could not be automatically migrated to the new CSS configuration format, so your CSS has been
│ updated to load your existing configuration file.
│ Migrating templates…
│ ↳ Migrated templates for configuration file: `./tailwind.config.js`
│ Migrating stylesheets…
│ ↳ Migrated stylesheet: `./src/styles/theme/shadcn.css`
│ Migrating PostCSS configuration…
│ ↳ Installed package: `@tailwindcss/postcss`
│ ↳ Removed package: `autoprefixer`
│ ↳ Removed package: `postcss-import`
│ ↳ Migrated PostCSS configuration: `./postcss.config.js`
│ Updating dependencies…
│ ↳ Updated package: `prettier-plugin-tailwindcss`
│ ↳ Updated package: `tailwindcss`
│ Verify the changes and commit them to your repository.
npm verb exit 0
npm info ok
It can be seen that most of the work was completed automatically, including updates to class names like flex-grow
-> grow
/ flex-shrink
-> shrink
, indicating a successful migration. It seems that there were no apparent issues on the surface. Let's try upgrading another Astro 5.1 project by running the update script.
% sudo npx @tailwindcss/upgrade@next
npm verb cli /usr/local/bin/node /usr/local/lib/node_modules/npm/bin/npm-cli.js
npm info using [email protected]
npm info using [email protected]
npm verb title npm exec @tailwindcss/upgrade@next
npm verb argv "exec" "--" "@tailwindcss/upgrade@next"
npm verb logfile logs-max:10 dir:/Users/cosine/.npm/_logs/2025-02-03T10_01_41_235Z-
npm verb logfile /Users/cosine/.npm/_logs/2025-02-03T10_01_41_235Z-debug-0.log
npm sill logfile start cleaning logs, removing 1 files
npm sill logfile done cleaning log files
npm http fetch GET 200 https://registry.npmjs.org/@tailwindcss%2fupgrade 489ms (cache updated)
≈ tailwindcss v4.0.2
│ Searching for CSS files in the current directory and its subdirectories…
│ ↳ Linked `./tailwind.config.mjs` to `./src/styles/global/tailwind.css`
│ Migrating JavaScript configuration files…
│ ↳ Could not load the configuration file: undefined is not a function
npm verb exit 1
npm verb code 1
Great, the error Could not load the configuration file: undefined is not a function
indicates that there are incompatible plugins. (Could not load the configuration file: v is not a function · tailwindlabs/tailwindcss · Discussion #15781 · GitHub)
I noticed that the previously successful migration project had these two plugins: tailwindcss-animate
and @tailwindcss/typography
.
The problematic Astro project had an additional tailwind-clip-path
plugin, and commenting it out allowed the migration to proceed normally.
// tailwind.config.js
module.exports = {
plugins: [
require("@tailwindcss/container-queries"),
require("tailwindcss-animate"),
// require("tailwind-clip-path"),
require("@tailwindcss/typography"),
],
};
Then let's give it a try:
> [email protected] dev /Users/cosine/Documents/Programming/cos-space
> astro dev
Package subpath './nesting/index.js' is not defined by "exports" in /Users/cosine/Documents/Programming/cos-space/node_modules/.pnpm/@[email protected][email protected]_@[email protected][email protected][email protected][email protected]._5qh5alcn5ztelwntajptz64i4q/node_modules/tailwindcss/package.json imported from /Users/cosine/Documents/Programming/cos-space/node_modules/.pnpm/@[email protected][email protected]_@[email protected][email protected][email protected][email protected]._5qh5alcn5ztelwntajptz64i4q/node_modules/@astrojs/tailwind/dist/index.js
Stack trace:
at exportsNotFound (node:internal/modules/esm/resolve:304:10)
at packageResolve (node:internal/modules/esm/resolve:837:14)
at defaultResolve (node:internal/modules/esm/loader:359:25)
at ModuleLoader.resolve (node:internal/modules/esm/loader:322:34)
at ModuleLoader.import (node:internal/modules/esm/loader:322:34)
ELIFECYCLE Command failed with exit code 1.
Good, I knew the migration in Astro wouldn't be that simple. I checked astro/packages/integrations/tailwind/CHANGELOG.md at main · withastro/astro · GitHub and found that Tailwind CSS now provides a Vite plugin, which is the preferred method for using Tailwind 4 in Astro. I uninstalled the original @astrojs/tailwind
and followed the Tailwind documentation for manual installation.
I also need to upgrade the Astro version to Astro 5.2 | Astro.
npx @astrojs/upgrade
pnpm rm @astrojs/tailwind
pnpm i tailwindcss @tailwindcss/vite
Success! Let's compare the configuration files.
diff --git a/astro.config.mjs b/astro.config.mjs
index bf8e9b1..20513bd 100644
--- a/astro.config.mjs
+++ b/astro.config.mjs
@@ -1,22 +1,17 @@
// @ts-check
import react from '@astrojs/react';
-import tailwind from '@astrojs/tailwind';
import { siteConfig } from './src/constants/site-config';
import icon from 'astro-icon';
import { defineConfig } from 'astro/config';
import svgr from 'vite-plugin-svgr';
import umami from '@yeskunall/astro-umami';
+import tailwindcss from '@tailwindcss/vite';
// https://astro.build/config
export default defineConfig({
site: siteConfig.site,
integrations: [
react(),
- tailwind({
- // Allow writing nested CSS declarations based on Tailwind's syntax
- nesting: true,
- applyBaseStyles: false,
- }),
icon({
include: {
gg: ['*'],
@@ -35,7 +30,7 @@ export default defineConfig({
enabled: true,
},
vite: {
- plugins: [svgr()],
+ plugins: [svgr(), tailwindcss()],
},
trailingSlash: 'never',
});
diff --git a/tailwind.config.mjs b/tailwind.config.mjs
index a7de2d0..28e5899 100644
--- a/tailwind.config.mjs
+++ b/tailwind.config.mjs
@@ -140,10 +140,5 @@ export default {
},
},
},
- plugins: [
- require('@tailwindcss/container-queries'),
- require('tailwindcss-animate'),
- require('tailwind-clip-path'),
- require('@tailwindcss/typography'),
- ],
+ plugins: [require('@tailwindcss/container-queries'), require('tailwindcss-animate'), require('@tailwindcss/typography')],
};
The original plugins became ineffective, and the @plugin
import no longer works, but it can still be written directly in CSS without issue. Also, the layer hierarchy issue may cause some style inheritance problems. Overall, migrating these two small projects was relatively smooth. I will continue to update this article for future migrations.
Summary of Upgrade Solutions#
Issue 1: Astro PostCSS Configuration Conflict#
Error: Package subpath './nesting/index.js' is not defined by "exports" in...
Response Strategy:
- Upgrade Astro to version 5.2+
npx @astrojs/upgrade
- Uninstall
@astrojs/tailwind
- Clean up old PostCSS plugin dependencies
- Follow the Tailwind documentation for manual installation to install
tailwindcss @tailwindcss/vite
/astro add tailwind