Blazor with TailwindCSS

Ever wondered how to use TailwindCSS with Blazor? Let's make it work!

Setup

There are only two things we need: A freshly created Blazor project and we need NodeJS. For the latter one, we need to install the necessary packages and to create the css.

So, let's start with installing all packages in the root directory of our Blazor projects:

npm install tailwindcss postcss autoprefixer

This should create some files like a package.json. To setup TailwindCSS, use the following command:

npx tailwindcss init -p

Now we have a tailwind.config.js and a postcss.config.js. Click the links to dive deeper into the topics. To make tailwind work with Blazor, we have to adopt the tailwind.config.js to detect razor files as valid target.

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    './**/*.html',
    './**/*.razor'
  ],
  mode: 'jit',
  theme: {
    extend: {},
  },
  plugins: [],
}

As you can see we targeted every html and razor file. We are also using jit mode, that was "recently" introduced. You can check the docs for more information. Let's continue. We have now to add some of the tailwind css files into our app.css:

@tailwind base;
@tailwind components;
@tailwind utilities;

html, body {
    font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
}
...

As we have to compile the file into a new css file, we have to adopt a new file that we use as our css:

<!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="bootstrap/bootstrap.min.css" />
    <!-- Here we changed from app.css to styles.css -->
    <link rel="stylesheet" href="styles.css" />
    <link rel="stylesheet" href="BlazorAppWithTailwind.styles.css" />
    <link rel="icon" type="image/png" href="favicon.png"/>
    <HeadOutlet/>
</head>

So with this we can create our output file:

 npx tailwindcss -i ./wwwroot/app.css -o ./wwwroot/styles.css --minify

Now where this is nice and handy for now - that isn't create that we have to do this everytime we change something in our css file. Of course, we could use the watch option via the CLI tools, but that also isn't the best option, as your CI/CD server shouldn't use such stuff. So instead we will extend the build process, so that everytime we built the project, we will generate the CSS file. For that we can make use our pacakge.json and add the following script:

{
  "scripts": {
    "build:css": "tailwindcss -i ./wwwroot/app.css -o ./wwwroot/styles.css --minify"
  },
  "dependencies": {
    "autoprefixer": "^10.4.16",
    "postcss": "^8.4.31",
    "tailwindcss": "^3.3.3"
  }
}

So everytime when we run npm run build:css it will create our stylesheet. So the last part we have to tell MSBuild to call that when we build. And this we can do via MSBuild Targets:

<Project Sdk="Microsoft.NET.Sdk.Web">

    <PropertyGroup>
        <TargetFramework>net8.0</TargetFramework>
        <Nullable>enable</Nullable>
        <ImplicitUsings>enable</ImplicitUsings>
    </PropertyGroup>

    <Target Name="PostBuild" AfterTargets="PostBuildEvent">
        <Exec Command="npm run build:css" />
    </Target>
</Project>

With that setup in place, let us use tailwindcss for the Clicker Button:

<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded" @onclick="IncrementCount">
    Click me
</button>

Button

You can check the repository in the resources if you want to dive into the code and configuration.

Resources

  • Source code to this blog post: here
  • All my sample code is hosted in this repository: here

Blazor .NET 8 - Enhanced Form Navigation

There are many new cool features with .NET 8 and Blazor in particular. In this blog post, I want to highlight a feature that I believe is very useful in the new context Blazor is living.

.NET 8 and Blazor United / Server-side rendering

New .NET and new Blazor features. In this blog post, I want to highlight the new features that are hitting us with .NET 8 in the Blazor world. So let's see what's new.

Blazor Project Structure

Did you ever wonder what is a nice way of structuring your Blazor application?

I will show you how I structure my Blazor projects (as well as this very blog). What are the upside in contrast to the "default" structuring you get with the Blazor template.

An error has occurred. This application may no longer respond until reloaded. Reload x