TailwindCSS è un framework CSS recente che utilizza un approccio diverso rispetto a quelli più conosciuti (come Bootstrap). Diverso nel senso che non offre componenti UI pronti all’uso, bensì una serie di classi utility che possono essere usate per comporre la UI delle nostre applicazioni.
È basato su PostCSS, e questo ci garantisce grande flessibilità nel comporre e estendere le classi già presenti. Dalla versione 3.0 inoltre, è stato introdotto un miglior supporto all’ hot-reload, consentendoci di sviluppare le nostre applicazioni in maniera ancora più rapida.
Vediamo insieme come integrare TailwindCSS nelle nostre applicazioni Blazor. Utilizzeremo Blazor WebAssembly, ma la procedura si applica allo stesso modo anche per Blazor Server.
Creazione di un applicazione Blazor
Per prima cosa, creiamo un’applicazione Blazor WebAssembly utilizzando il template standard. Potete usare il vostro IDE preferito, oppure usare la CLI di dotnet:
dotnet new blazorwasm -o BlazorWind
A questo punto possiamo eliminare alcuni file già presenti, come i componenti Razor e Bootstrap. Dovremmo ottenere un risultato simile a questo. Il file app.css è stato lasciato poiché contiene alcuni stili ancora utili, come ad esempio quello per il messaggio di eccezione non gestita. Lo riutilizzeremo più in avanti.

Integriamo TailwindCSS
TailwindCSS è basato su PostCSS, un tool che permette di usare alcune funzionalità non presenti in CSS. Per questo motivo è necessario eseguire uno step di transpilazione per generare il file CSS finale, che sarà distribuito agli utenti. Per poterlo usare, è necessario installare Nodejs sulla propria macchina di sviluppo. Ovviamente, se si vuole distribuire l’applicazione come immagine Docker, sarà necessario installarlo anche in fase di build dell’immagine stessa.
Una volta installato NodeJS sulla nostra macchina di sviluppo, possiamo procedere con la creazione di un progetto Node all’interno della cartella del nostro progetto Blazor. Dalla vostra shell preferita:
npm init -y
npm install -D tailwindcss@latest postcss autoprefixer cross-env
npx tailwindcss init
Una volta terminato, notiamo che sono stati aggiunti diversi file all’interno del nostro progetto. Ci interessano principalmente:
tailwind.config.js
packages.json
Il primo contiene le configurazioni necessarie al parser di TailwindCSS. Per generare un file CSS minimizzato, il parser cerca tutte le classi utilizzate all’interno del nostro progetto. Così facendo il CSS conterrà solo il codice realmente utilizzato dalla nostra applicazione, riducendone le dimensioni. In particolare ci interessa definire In quali file dovranno essere cercate le classi di Tailwind:
module.exports = {
content: [
"**/*.razor",
"**/*.razor.cs",
"**/*.cshtml",
"**/*.html"
],
theme: {
extend: {},
},
plugins: [],
}
A questo punto creiamo il nostro file PostCSS. Possiamo sfruttare il file css che abbiamo risparmiato in precedenza. All’interno della root del nostro progetto, creiamo una directory Styles
e spostiamo il file app.css
, cambiandogli anche l’estensione in app.pcss
.
mkdir Styles
mv wwwroot/css/app.css Styles/app.pcss
Fatto ciò, ci resta da configurare il sistema di build per transpilare dal PostCSS al CSS in fase di compilazione del progetto dotnet. Per farlo, aggiungiamo due script al file package.json
:
//...
"scripts": {
"build": "cross-env NODE_ENV=development ./node_modules/tailwindcss/lib/cli.js -i ./Styles/app.pcss -o ./wwwroot/css/app.min.css",
"watch": "cross-env NODE_ENV=development ./node_modules/tailwindcss/lib/cli.js -i ./Styles/app.pcss -o ./wwwroot/css/app.min.css --watch"
},
//...
E successivamente aggiungiamo uno step di PostBuild
al file di progetto dell’applicazione Blazor. Così configurato, lo step transpilerà il foglio di stile PostCSS dopo la compilazione dell’app .NET. Inoltre, configurando i parametri Inputs
ed Outputs
, il sistema di build lancierà la transpilazione solo nel caso in cui i file siano effettivamente cambiati.
<Target Name="PostBuild" AfterTargets="PostBuildEvent"
Inputs="Styles\app.pcss"
Outputs="wwwroot\css\app.min.css">
<Exec Command="npm run build" />
</Target>
Ci resta solo da aggiornare il file index.html
per includere il file app.min.css
(al posto del vecchio app.css
), e abilitare l’hot reload per i file statici.
<link href="css/app.min.css" rel="stylesheet" />
<!-- hot reload css files -->
http://_framework/aspnetcore-browser-refresh.js
A questo punto possiamo sia buildare la nostra applicazione usando dotnet build, che eseguirla con hot-reload abilitato. Per quest’ultimo, sarà necessario lanciare il watch sia per PostCSS che per Blazor.
npm run watch
dotnet watch
L’applicazione è in esecuzione! Proviamo a vedere se l’hot-reload funziona:
html, body {
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
background-color: red;
}


Funziona!
Creazione di un componente con TailwindCSS
L’infrastruttura è settata, ma non abbiamo ancora utilizzato TailwindCSS. Lanciando l’applicazione avrete sicuramente notato che qualcosa è cambiato, ovvero sono scomparsi gli stili relativi agli headings (h1, h2, h3). Questo è un comportamento voluto: TailwindCSS li resetta, lasciando a noi la scelta su come stilizzarli. Per ripristinare gli stili di default, possiamo reintegrarli nel file app.pcss
. Basta aggiungere in capo al file:
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
h1 {
@apply text-2xl;
}
h2 {
@apply text-xl;
}
h3 {
@apply text-lg;
}
a {
@apply text-blue-600 underline;
}
}
Usando PostCSS, abbiamo prima importato, poi riutilizzato le classi di TailwindCSS (text-2xl
, text-xl
, etc.) sugli elementi di tipo h1, h2, h3, ed a. A questo punto il testo “Hello world” è più grande.
Ora che abbiamo incluso realmente TailwindCSS, proviamo a creare un nuovo componente. Proveremo a replicare (spoiler: con scarso successo) la navbar del blog BlazorDevIta. In Shared
, creiamo un nuovo componente Navbar.razor
:
<nav class="bg-white shadow-lg">
<div class="max-w-12xl mx-auto px-4">
<div class="flex justify-between space-x-7">
<a id="nav-logo" href="#" class="flex items-center py-4 px-2">
<img src="https://blazordev.it/wp-content/uploads/2022/01/logo-blazordevita.svg"
alt="Logo"
class="h-16 mr-2"/>
</a>
<div class="hidden md:flex items-center space-x-4 font-semibold">
<NavLink href="">
<span class="py-4 px-2 text-violet-500 hover:text-violet-800 transition duration-300">Home</span>
</NavLink>
<NavLink href="">
<span class="py-4 px-2 text-violet-500 hover:text-violet-800 transition duration-300">About</span>
</NavLink>
<NavLink href="">
<span class="py-4 px-2 text-violet-500 hover:text-violet-800 transition duration-300">Contacts</span>
</NavLink>
</div>
</div>
</div>
</nav>
E includiamo questo componente nel MainLayout
:
@inherits LayoutComponentBase
<div class="page">
<Navbar/>
<main>
<div class="top-row px-4">
<a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a>
</div>
<article class="content px-4">
@Body
</article>
</main>
</div>

Per concludere
Che dire, la nuova Navbar non è certo all’altezza di quella originale, ma come esempio rende bene l’idea delle potenzialità di questo (discusso) framework. Trovate il codice d’esempio su GitHub.
Sia che siate promotori, sia che siate detrattori di TailwindCSS, adesso sapete come utilizzarlo nelle vostre applicazioni Blazor! Non mi resta altro da fare che augurarvi,
Happy coding!