Tailwind, Blazor and Sisyphus
Turns out everywhere I turned I was getting instructions for installing Tailwind v3 and not v4. But Tailwind itself was installing v4.
And in some cases, AI was comingling the instructions. That accounts for nonsense that follows.
If you want an updated and, likely, correct set of instructions, go here.
This might be the most painful experience I've had in a while. At the end of the day, there were just an unimaginable number of opaque, undocumented instructions that led to enormous amounts of wasted time.
What resulted is a trial-and-error, half-assed, kinda-working, sorry-excuse for configuration of any product in 2025.
90% of these problems come from unfamiliarity with Tailwind, Node and other pretty important parts. But I imagine that's pretty typical for a junior Blazor developer.
I'm almost certain there's a better way to do this. I sure couldn't figure it out - and that's on me. It would sure be great if Tailwind or anyone else brought the docs up to date.
Steps to create a dotnet 9 Blazor Interactive Auto app that uses Tailwind:
- Create the project
dotnet new blazor -n <your-project-name-here> -ai -e -int Auto -au Individual
This will yield a solution with two projects.
server
project.- In the
Properties
folder, edit thelaunchSettings.json
file and add the following lines to the profile sections markedhttp
andhttps
.
"hotReloadEnabled": true ,
"watchStaticFiles": true,
- In the
wwwroot
folder empty out theapp.css
file and replace the contents with these lines:
@import "tailwindcss";
@tailwind utilities;
- In the project root folder, create a
tailwind.config.js
file with these lines:
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./**/*.{razor,html,cshtml}",
],
theme: {
extend: {},
},
plugins: [],
}
- Still in the project root, create a
postcss.config.js
file with these lines:
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
}
}
- Edit the
App.razor
file, removing the CSS directives and replace it with the one below. This means all styling will come from the file that was processed by Tailwind:
<link rel="stylesheet" href="@Assets["app.min.css"]" />
- Open a terminal app in the server project root and enter this command to install
tailwind/cli
globally:
npm install -g tailwindcss @tailwindcss/cli
- Then enter this command to install the other node nonsense needed:
npm install tailwindcss @tailwindcss/cli postcss autoprefixer postcss-cli
- Still in the root of the project type this:
npx tailwindcss -i wwwroot/app.css -o wwwroot/app.min.css --watch
- Open another terminal window in the server project root and type this:
dotnet watch
At this point, you should be able to use tailwind commands in the server project and have them reflected in the web page that got launched. That said - there's no IntelliSense.
app.min.css
. And that's because we're not scanning for it. If you use that class in the server project, then the
npx
processor picks it up, adds it to app.min.css
and it suddenly becomes available to the client project and it works.tailwind.config
to respect the content
line and scan the client project (not shown here), it simply would not do it. I have no idea why.A workaround exists for using classes only in the client project. If you change the following lines in the head
section of App.razor:
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="@Assets["app.min.css"]" />
You get to play around with tailwind. That said, in Tailwind v4, they suggest another command and it didn't work for me (and others).
Hot reload is a little hit or miss with this in place, and there's still no Intellisense.
Good luck.