---
title: "Tailwind v4 with Blazor - It just got easier"
description: "**Tailwind** version 4 [was just released](https://tailwindcss.com/blog/tailwindcss-v4). With the new CLI, it is just so much easier to use tailwindcss with **Blazor**. So in this post, I will show you how to use the new CLI to create a new Blazor project with Tailwind v4.\n\nShort disclaimer: If you still want to use version 3, I already wrote an article about this some time ago: [*\"Blazor with TailwindCSS\"*](https://steven-giesel.com/blogPost/351838ba-e308-4a09-b9f6-75bb95c39610/blazor-with-tailwindcss)."
updated: 2025-03-03
tags: ["C#", "Blazor", "TailwindCSS", ".NET", "Tailwind"]
canonical: "https://steven-giesel.com/blogPost/364c43d2-b31e-4377-8001-ac75ce78cdc6/tailwind-v4-with-blazor-it-just-got-easier"
---

# Tailwind v4 with Blazor - It just got easier

**Tailwind** version 4 [was just released](https://tailwindcss.com/blog/tailwindcss-v4). With the new CLI, it is just so much easier to use tailwindcss with **Blazor**. So in this post, I will show you how to use the new CLI to create a new Blazor project with Tailwind v4.

Short disclaimer: If you still want to use version 3, I already wrote an article about this some time ago: [*"Blazor with TailwindCSS"*](https://steven-giesel.com/blogPost/351838ba-e308-4a09-b9f6-75bb95c39610/blazor-with-tailwindcss).

## `tailwind/cli`

The basic installation setup is taken from the official documentation: https://tailwindcss.com/docs/installation/tailwind-cli
I will link the sample repository at the end of this post so you can see the full setup. 

But here the short gist:

0. Create a new Blazor project
You can either use your favorite IDE or the dotnet CLI to create a new Blazor project. I will use the dotnet CLI for this example:
```bash
dotnet new blazor -o BlazorTailwind
```

1. Install the cli with tailwind:

```bash
npm install tailwindcss @tailwindcss/cli
```

This will create a `package.json` (and `package-lock.json`) file and a `node_modules` folder. Therefore I would recommend adding the `node_modules` folder to your `.gitignore` file. The package.json looks like this:
```json
{
  "dependencies": {
    "@tailwindcss/cli": "^4.0.8",
    "tailwindcss": "^4.0.8"
  }
}
```

2. Use tailwind


Inside your `wwwroot/app.css` add tailwind like this on the first line:
```css
@import "tailwindcss";
```

3. Generate the merged css file


We are almost done. The last step is to generate the generated CSS file which consists of all the tailwind classes and your custom definitions in your `wwwroot/app.css` file. You can do this by running the following command:

```bash
npx @tailwindcss/cli -i wwwroot/app.css -o wwwroot/dist.css
```

This will generate a `dist.css` file in your `wwwroot` folder. You can now include this file in your `App.razor` instead of the `app.css` file like this:

```html
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <base href="/"/>
    <link rel="stylesheet" href="dist.css"/>
    <link rel="stylesheet" href="@Assets["BlazorTailwind4.styles.css"]"/>
```

Now let's go to our `Home.razor`, use some tailwind classes and run the `npx` command again:
```html
<h1 class="p-4 font-bold text-blue-600">Hello, world!</h1>
```

Will result in:

![Hello World](https://linkdotnetblog.azureedge.net/blog/20250303_Tailwind4/HelloWorld.webp)

Now you might have seen, that I did not use the `@Assets` directive. And there is a reason. The process I showed is very manual and you have to run the command every time you change something in your `app.css` file. But there is a better way to do this. 

## Automate the process
We can use the `npx` command to get executed everytime we build the project. For that let's go to our `package.json`:
```json
{
    "dependencies": {
        "@tailwindcss/cli": "^4.0.8",
        "tailwindcss": "^4.0.8"
    },
    "scripts": {
        "build:css": "npx @tailwindcss/cli -i wwwroot/app.css -o wwwroot/dist.css"
    }
}
```

With `scripts` we can execute commands. So we can now run `build:css` everytime we build. To do that, just add the following line to your `.csproj` file:
```xml
<Target Name="PreBuild" BeforeTargets="PreBuildEvent">
    <Exec Command="npm run build:css" />
</Target>
```

Now everytime you build your project, the `dist.css` file will be generated. That said, you might want to `gitignore` the `dist.css` file, because it will be generated everytime you build the project anyway. No need to keep the autogenerated file in your repository.

### GitHub Actions

The unfortunate thing is, that you have to have node installed on your machine or your GitHub action. So to make a minimal CI pipeline work, you want to have something like this:

```yml
name: Build

on:
  push:
    branches:
      - main
  workflow_dispatch:

jobs:
  build:
    runs-on: windows-latest
    permissions:
      contents: read

    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
      - run: npm install

      - name: Set up .NET Core
        uses: actions/setup-dotnet@v4
        with:
          dotnet-version: '9.x'

      - name: Build with dotnet
        run: dotnet build --configuration Release
```

## `dotnet watch`

If you are like me, you are using `dotnet watch` aka hot-reload all the time. But there is an inherit problem with tailwindcss and the stuff we built up earlier. `dotnet watch` **does not** invoke the pre-build event. So to come around that fact you basically need two shells open. The first one for your `dotnet watch` and the second to let tailwind watch your code:

```bash
npx @tailwindcss/cli -i wwwroot/app.css -o wwwroot/dist.css --watch
```

Now tailwind automatically recognizes changes in your `app.css` file and updates the `dist.css` file. Of course you can also park that in your `package.json`:
```json
{
  "dependencies": {
    "@tailwindcss/cli": "^4.0.8",
    "tailwindcss": "^4.0.8"
  },
  "scripts": {
    "build:css": "npx @tailwindcss/cli -i wwwroot/app.css -o wwwroot/dist.css",
    "watch:css": "npx @tailwindcss/cli -i wwwroot/app.css -o wwwroot/dist.css --watch"
  }
}
```
And just call `npm run watch:css`

## Resources
 * Source code to this blog post: [here](https://github.com/linkdotnet/BlogExamples/tree/main/BlazorTailwind4)
 * All my sample code is hosted in this repository: [here](https://github.com/linkdotnet/BlogExamples)