banner
cos

cos

愿热情永存,愿热爱不灭,愿生活无憾
github
tg_channel
bilibili

Tailwind CSS v4.0 Upgrade and Astro 5.2 Project Migration Record

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, and color-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. Renamed bg-gradient-* to bg-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-* and inset-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.
  • 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 - The inert variant allows you to style elements marked with the inert attribute, useful for adding visual cues to indicate that parts of the content are not interactive.
  • New nth-* Variants - Use nth-* and nth-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 like nth-[2n+1_of_li]. e.g.: nth-3:underline nth-last-5:underline nth-last-of-type-6:underline.
  • New in-* Variants - Very similar to group-*, but without the group class.
    • The in-* variants respond to any parent's state changes, so if you want finer control, you need to use group instead.
  • Support for :popover-open - Existing open 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.

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:

  1. Upgrade Astro to version 5.2+ npx @astrojs/upgrade
  2. Uninstall @astrojs/tailwind
  3. Clean up old PostCSS plugin dependencies
  4. Follow the Tailwind documentation for manual installation to install tailwindcss @tailwindcss/vite / astro add tailwind
Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.