TailwindCSS 4.0 upgrade for Typhoon Premium Theme

Providing all new performance-oriented features

8 mins

TLDR: This document outlines the steps required to upgrade an existing Tailwind 3 version of the Typhoon Premium Theme to Tailwind 4.

This is a major update and probably worth your while getting your theme updated to ensure you can take advantage of all the cool new stuff available as part of the Tailwind CSS v4.0 release.

There are fundamental architectural changes in version 4 that requires an initial automatic migration process, followed by some CLI work to upgrade tailwind and modify some scripts, then various fixes in the CSS files to address changed classnames, and lastly some fixes to ensure CSS is loaded with the same specificity as the existing version to minimize the customization to CSS. There's a lengthy Upgrade Guide available in the TailwindCSS documentation, but this guide below shows you the bits specific for Typhoon's configuration.

1. Automated Migration Process

The first step in the process is to use the TailwindCSS automatic migration. In order to do this, we first have to cleanup our tailwind.config.js a little bit or the migration will error.

Open up the tailwind.config.js file in your editor and remove the normalize() method that wraps the exports content and because that's removed you can also remove the related consts:

Before:

const colors = require('tailwindcss/colors');  
const path = require('path');  
const process = require('process');  
const dirname = process.env.PWD || process.cwd();  
const normalize = (paths) => {  
  return paths.map((_path) => path.normalize(`${dirname}/${_path}`));  
}  
module.exports = {  
  content: normalize([  
    '../../config/**/*.yaml',  
    '../../pages/**/*.md',  
    './blueprints/**/*.yaml',  
    './js/**/*.js',  
    './templates/**/*.twig',  
    './typhoon.yaml',  
    './typhoon.php',  
    './available-classes.md',  
    '../../plugins/sandbox-support/templates/**/*.twig',  
  ]),
...

After:

const colors = require('tailwindcss/colors');  

module.exports = {  
  content:[  
    '../../config/**/*.yaml',  
    '../../pages/**/*.md',  
    './blueprints/**/*.yaml',  
    './js/**/*.js',  
    './templates/**/*.twig',  
    './typhoon.yaml',  
    './typhoon.php',  
    './available-classes.md',  
    '../../plugins/sandbox-support/templates/**/*.twig',  
  ],

normalize() was used to get the full path of each of the exports in order to handle symlinks better. This is really only used when your theme is symlinked inside a project. This is quite rare, and generally not needed anymore with Tailwind's improved search mechanism.

Next remove the incompatible plugins multi-column and debug-screens. Luckily TailwindCSS now has great support for CSS columns and this plugin is no longer required. The debug-screens plugin was useful to see the screen size, but it's not essential and is not currently supported in Tailwind4.

Before:

plugins: [  
  require('@tailwindcss/typography'),  
  require('@tailwindcss/forms'),  
  require('tailwindcss-multi-column')(),  
  require('tailwindcss-debug-screens'),  
],

After:

plugins: [  
  require('@tailwindcss/typography'),  
  require('@tailwindcss/forms'),  
],

Then remove those too plugin dependencies:

npm remove tailwindcss-debug-screens tailwindcss-multi-column

Now we can run the automated upgrade process which will update the NPM packages, make changes to twig templates to switch any old class names to new ones. Run this from the root of your Typhoon (or Typhoon derived theme):

npx @tailwindcss/upgrade

You should get some output similar to this:

➜ npx @tailwindcss/upgrade
≈ tailwindcss v4.0.3

fatal: not a git repository (or any of the parent directories): .git
│ Searching for CSS files in the current directory and its subdirectories…

│ ↳ Linked `./tailwind.config.js` to `./css/site.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: `./css/site.css`

│ Migrating PostCSS configuration…

│ ↳ The PostCSS config contains dynamic JavaScript and can not be automatically migrated.

│ Updating dependencies…

│ ↳ Updated package: `tailwindcss`

At this point you should be upgrade to TailwindCSS 4.0, however you will note in the output of the migration command a few things could not be automatically migrated. Regarding the tailwind.config.js we'll leave this as is and not manually migrate to the new 4.0 way of doing things entirely with CSS variables. We'll stick to importing the existing tailwind js file for now. We do have to fix the PostCSS configuration however.

2. Manual Migration Steps

First we need to modify the postcss.config.js file. It only needs a single command now, and it should be renamed to postcss.config.mjs as it's now an ES module.

Before (postcss.config.js):

module.exports = {  
  plugins: [  
    require('postcss-import'),  
    require('tailwindcss/nesting'),  
    require('tailwindcss'),  
    require('autoprefixer'),  
  ],  
}

After (postcss.config.mjs):

export default {  
  plugins: {  
    "@tailwindcss/postcss": {},  
  },  
};

We need to be able to use the CLI commands, and there are no longer included in the tailwindcss binary so we need to manually install this package:

npm install @tailwindcss/cli 

Also, the commands in the package.json to kick of the dev and prod processes to compile the CSS with postCSS need to be modified.

NOTE: if you have the old watch and build commands you can remove those now, as we have moved to dev and watch but they do the same thing as before.

Before:

"scripts": {  
  "dev": "tailwindcss -i ./css/site.css -o ./build/css/site.css --postcss --watch --minify --verbose",  
  "prod": "NODE_ENV=production tailwindcss -i ./css/site.css -o ./build/css/site.css --postcss --minify"  
},

After:

"scripts": {  
  "dev": "npx @tailwindcss/cli -i ./css/site.css -o ./build/css/site.css --watch --minify --verbose",  
  "prod": "NODE_ENV=production npx @tailwindcss/cli -i ./css/site.css -o ./build/css/site.css --minify"  
},

NOTE: the command has been changed from tailwindcss to @tailwindcss/cli and we no longer need the --postcss flag.

Now we can try to compile the CSS with the CLI command:

npm run dev

> [email protected] dev
> npx @tailwindcss/cli -i ./css/site.css -o ./build/css/site.css --watch --minify --verbose

Error: Cannot apply unknown utility class: bg-opacity-10

As you can see we have an error that is due to a deprecated class being used. It's time for some cleanup!

3. CSS Cleanup

There are quite a few deprecated utilities and these will throw an error. The previous compile told us that bg-opacity-10 class is deprecated and this is correct, you know set the opacity on the bg color itself with the /10 modifier. In this case, I searched the files in Typhoon for bg-opacity- and found the culprit in css/custom/dark.css line 17:

Before:

pre {
  @apply bg-blue-300 bg-opacity-10 text-blue-200;
}

After:

pre {
  @apply bg-blue-300/10 text-blue-200;
}

This one change allowed me to run the dev command and get a successful compile:

npm run dev

> [email protected] dev
> npx @tailwindcss/cli -i ./css/site.css -o ./build/css/site.css --watch --minify --verbose

≈ tailwindcss v4.0.3

Done in 107ms

At this point we are up and running with TailwindCSS 4.0, but if you take a look in your browser you might not see things 100% as you expect, the text is not quite the right color. It's particularly pronounced in dark mode. This is caused by an errant text color that should never of been there, but this version of tailwind has exposed as a problem.

Also while we're at it, and as we are not using the unsupported debug-screens plugin we can remove the two offending bit of CSS in one go. To do this simple edit the css/typography.css and remove this body {} block completely:

Remove:

body {
  &.debug-screens:before {
    @apply left-inherit right-0;
  }

  @apply text-gray-700;
}

That's it!

If you have been running npm run dev, then these changes will be picked up and you can refresh your site and it should look pretty close (if not exactly the same) to how it looked with Tailwind3.

4. Next Steps

The previous steps will get you to a running state with Tailwind 4, and you can continue on with development taking advantage of the cool new functionality. However, these are just the bare-minimum steps required to get things compiling again, and to fully switch over to the 4.0 way of doing things, requires significantly more work.

The most fundamental change is moving away from the tailwind.config.js approach for configuration, and moving towards 4.0's CSS variable-driven configuration. Being the first release, not everything we could do in he JS file is available, and other things require a bit more verbose (but probably more semantic) ways of doing things.

There are just too many individual tweaks and changes to document here, but the next major release of the Typhoon Premium Theme will be fully upgraded, not just to be Tailwind4 compatible. Typhoon will be fully migrated away from tailwind.config.js, using the highly popular and new default vite build tool, and many CSS related cleanups.

The following is a summary list of some of the changes that were made in Typhoon 4.0:

  • Recreated all custom configuration in site.css using CSS variables that used to be contained in tailwind.config.js
  • Moved from postcss to vite for a faster and simpler build process. The same npm run dev commands remain however.
  • Cleaned up various CSS elements that are no longer needed. E.g. default form placeholder colors, -webkit-mask-image fix removed, moved dark.css into .prose section of typography.css, moved social.css logic into typography.css and moved colors into CSS variables in site.css, moved some hardcoded CSS into Tailwind classes for consistency, various CSS menu styling fixes, changed previous columns plugin to use built-in columns CSS support from tailwind. Any much much more!

To really examine everything that changed you should backup your latest version of Typhoon 2.x (or Typhoon 2.x based theme), and then install the newest Typhoon 4.x release, then use a tool that supports directory-based diff/merge (such as Kaleidoscope for mac) and compare the files to see everything that changed.

Grav Premium
Turbo-charge your Grav site - from the creators of Grav