I’ve been a fan of Tailwind CSS for quite some time now. It was created by Adam Wathan and has been developed by Jonathan Reinink, David Hemphill, and Steve Schoger. I actually discovered Tailwind due to following Steve and his excellent tweets on UI tips and tricks. In fact, if you are a developer with an interest in UI design, I couldn’t recommend Steve’s eBook, RefactoringUI, enough.

Tailwind is a utility-first CSS framework, which means that instead of providing you with a set of premade UI components, which lead to every website looking the same, you are provided with a massive array of low-level utility classes that allow you to rapidly create custom designs with ease. Let me give you an example to illustrate.

Let’s look at styling a button with bootstrap first. We can define our button and apply the btn and btn-primary CSS classes as per the code below.

<button class="btn btn-primary">Primary</button>

This will render a button that looks like this.

Next, we’ll style a button using Tailwind.

<button class="px-3 py-2 rounded-md bg-blue-600 text-white">Primary</button>

Which will render a button that looks like this.

As you can see straight away, there are no tailored CSS classes in this version. The button is built up using multiple classes which each provide a single element of the styling. The px and py classes provide padding, rounded-md rounds the corners of the button, bg-blue-600 colours the background and text-white defines the text colour. You can checkout the full array of options on the Tailwind docs.

You’re probably thinking, but Chris, that’s a lot more styles I have to apply to get the same result. I agree, but what you’re getting in return is flexibility and the option to not have your site look like the thousands of others that use the same CSS framework. I appreciate this isn’t something that interests everyone and there is nothing wrong with using frameworks like bootstrap, I have for years and it’s awesome. But when you’re trying to do something a little different Tailwind is your friend.

Another huge benefit of using Tailwind is that you pretty much never have to write any CSS classes yourself. As everything is composable using utility classes, you can create any look, any style from what’s provided by the framework. Need your site to be responsive? No problem, Tailwind has utilities for that. Need cool transitions? Tailwind has you covered there, too.

Tailwinds approach sits really well with component based UIs, such as Blazor. Building on the example above we could create a PrimaryButton component which looks like this.

<!-- PrimaryButton.razor -->

<button class="px-3 py-2 rounded-md bg-blue-600 text-white"
        @onclick="HandleClick">@Text</button>

@code {
	[Parameter] public Action HandleClick { get; set; } 
	[Parameter] public string Text { get; set; } 
}

We’ve now nicely encapsulated the styles for our primary button in a component. And if we need to update the styles later down the road, we can come to a single place to make the changes.

It doesn’t stop there either. Tailwind can also be customised. This is because Tailwind is more than just a CSS framework, it’s written in PostCSS and can be configured to your needs. We’re going to be covering how to do this in part 2.

Integrating Tailwind with Blazor

Hopefully, if you’ve gotten this far, I’ve convinced you to try Tailwind—or you’re already a fan and just want to know how to use it with your Blazor app.

In order to get the most out of Tailwind, we’re going to be using some tools you may or may not be familiar with from the JavaScript ecosystem, NPM and Gulp. If you’re not familiar with these tools, I’ve added a link to each of them so you can have a read up on what they do.

Installing NodeJS to get NPM

If you haven’t already got NodeJS installed then you will need to do that first. This is because installing node installs NPM (Node Package Manager). Head over to the Node site and grab the latest LTS version (12.16.0 at the time of writing). Run the installer, you should be able to accept all the defaults, just make sure that npm package manager is selected.

Once the installer is finished, open a terminal and type npm -v. If you see a version number printed out then you’re good to go.

Adding Gulp and Tailwind via NPM

The next thing we need to do is install the Gulp CLI globally, this will allow us to work with Gulp on the command line. At your terminal type npm install gulp-cli -g. Once the install has completed we can turn our attention to our Blazor project.

In the root of your Blazor app, add a new file called package.json and then add the following code.

{
  "devDependencies": {
    "gulp": "^4.0.2",
    "gulp-postcss": "^8.0.0",
    "precss": "^4.0.0",
    "tailwindcss": "^1.2.0",
    "autoprefixer": "^9.7.4"
  }
}

This tells NPM what packages to install for our project. We’ll see how these are used a little later in when we configure Gulp.

The next step is to setup our CSS file as per the Tailwinds docs. The way I do this is by creating a folder in the root of my app called Styles and in there add a file called site.css (you can name this file whatever you want). The reason this file is sitting outside of the wwwroot folder is because it is it going to be processed to produce the final CSS file which will be outputted to the wwwroot folder. Then add the following code.

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

#blazor-error-ui {
    background: lightyellow;
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
}

    #blazor-error-ui .dismiss {
        cursor: pointer;
        position: absolute;
        right: 0.75rem;
        top: 0.5rem;
    }

The three lines at the top are all we need to add to get all of those awesome Tailwind utilities. When the file is processed, those three lines will be replaced with all the generated classes from Tailwind. You can also add any custom styles you want present in the final CSS file as well. I’ve made sure to keep the styling for the Blazor error messages which come in the default project template.

The last part is to add another file to the root of the project called gulpfile.js. This is where we are going to configure Gulp to build Tailwind for us. Add the following code, remember to update the filename if you didn’t use site.css.

const gulp = require('gulp');

gulp.task('css', () => {
  const postcss = require('gulp-postcss');

  return gulp.src('./Styles/site.css')
    .pipe(postcss([
      require('precss'),
      require('tailwindcss'),
      require('autoprefixer')
    ]))
    .pipe(gulp.dest('./wwwroot/css/'));
});

We’re defining a single Gulp task called css. It takes the site.css we defined above as an input and then runs it though a plugin called postcss. Essentially, this plugin builds all of those Tailwind utility classes. Once it’s finished, the processed CSS is output into the wwwroot/css folder.

With all of the above in place, open a terminal and navigate to the root of the Blazor app, the same folder where the package.json and gulpfile.js reside. Once there, run the following commands.

npm install
gulp css

The first command will install all the packages in the package.json file we created earlier. Once that’s finished, the second command executes the css task we defined in our gulpfile.js. If all has gone well you should see a new file, site.css in your wwwroot/css folder. All that’s left to do is to reference the file in your apps index.html or _Host.cshtml.

Congratulations! You can now go and start building your UI using the utility of Tailwind.

Summary

In this post, I’ve shown how to integrate the awesome, utility-first CSS framework, Tailwind CSS into your Blazor project. We started by looking at what makes Tailwind different to other CSS frameworks such as Bootstrap and reasons why we’d want to use it. We then looked at how we can integrate it with a Blazor application using NPM and Gulp.

I hope you enjoyed this post and if you didn’t know about Tailwind before, that I’ve made you curious about it. Next time, we’re going to go a little deeper down the rabbit hole. We’ll look at how we can customise Tailwind using it’s configuration system. As well as how we can optimise our outputted CSS by removing unused classes. To finish off we’ll go through how to integrate Tailwind into a CI pipeline with Azure DevOps.

I’m using Tailwind to build a new documentation site for the Blazored UI packages. So if you want to see this in a real world application then feel free to check it out on GitHub.