Tailwind CSS — typed, composable, and native to .NET.
BlazorTw is a lightweight enhancement layer for Tailwind CSS in Blazor. It brings the full power of Tailwind into the C# type system, providing IntelliSense, compile-time safety, and composable class sets without abstracting CSS away or adding runtime overhead.
Note: This package was created with the assistance of AI (JetBrains Junie / Claude).
BlazorTw doesn't replace Tailwind; it makes it feel native to the .NET ecosystem. Instead of typing strings and hoping for the best, you get a discoverable API that mirrors Tailwind's naming conventions perfectly.
- Stop Memorizing: Use IntelliSense to browse spacing scales, color palettes, and utility groups.
- Refactor with Confidence: Typed utilities mean you can use standard IDE tools to find usages and refactor styles.
- Zero Runtime Cost: Everything is resolved at compile time using Source Generators. It's fully compatible with AOT and Trimming (Blazor WASM).
- Tailwind v4 Ready: Built specifically for the CSS-first future of Tailwind v4.
# Core utilities and types
dotnet add package BlazorTw
# Optional: Source Generator (required for @theme sync)
dotnet add package BlazorTw.Generators
# Optional: Analyzers, giving build errors for invalid class combinations
dotnet add package BlazorTw.AnalyzersCombine utilities using the + operator. It's intuitive, readable, and type-safe.
@using BlazorTw
<div class="@(Tw.Flex + Tw.Items.Center + Tw.Gap._4 + Tw.P._6 + Tw.Bg.Slate._100 + Tw.Rounded.Xl)">
<div class="@(Tw.Size._12 + Tw.Bg.Blue._500 + Tw.Rounded.Full)" />
<div>
<h3 class="@(Tw.Text.Lg + Tw.Font.Semibold + Tw.Text.Slate._900)">Typed Tailwind</h3>
<p class="@(Tw.Text.Sm + Tw.Text.Slate._600)">No more typos in your class strings.</p>
</div>
</div>Variants are pre-built static tokens — fully type-safe and Tailwind scanner compatible.
// Hover and focus states
var style = Tw.Hover.Bg.Blue._600 + Tw.Focus.Ring._2;
// Responsive layouts
var layout = Tw.Flex + Tw.FlexCol + Tw.Md.FlexRow + Tw.Md.Items.Center;
// Dark mode
var dark = Tw.Dark.Bg.Gray._900 + Tw.Dark.Text.White;
// All 10 variants: Hover, Focus, Active, Disabled, Dark, Sm, Md, Lg, Xl, Xl2BlazorTw automatically synchronizes with your Tailwind v4 @theme block. If you define a custom spacing or color in your CSS, it instantly appears in your C# IntelliSense.
Note: This feature requires the
BlazorTw.Generatorspackage and your CSS file must be included asAdditionalFilesin your.csproj.
/* app.css */
@theme {
--color-brand-500: #6366f1;
--spacing-128: 32rem;
--font-display: 'Poppins', sans-serif;
--radius-pill: 9999px;
--shadow-glow: 0 0 10px #fff;
--ease-bounce: cubic-bezier(0.68, -0.55, 0.27, 1.55);
--breakpoint-3xl: 120rem;
}<!-- YourProject.csproj -->
<ItemGroup>
<AdditionalFiles Include="Styles/app.css" />
</ItemGroup>// Automatically available — all @theme namespaces are supported:
var custom = Tw.Bg.Brand._500 + Tw.P._128;
var card = TwTheme.Rounded.Pill + TwTheme.Shadow.Glow;
var heading = TwTheme.Font.Display + TwTheme.Ease.Bounce;All 20 Tailwind v4 @theme namespaces are supported: --color-*, --spacing-*, --font-*, --text-*, --font-weight-*, --tracking-*, --leading-*, --tab-size-*, --breakpoint-*, --container-*, --radius-*, --shadow-*, --inset-shadow-*, --drop-shadow-*, --blur-*, --perspective-*, --zoom-*, --aspect-*, --ease-*, and --animate-*.
Create reusable style sets as static constants. This is the perfect way to build a consistent design system for your components.
public static class Theme
{
public static readonly ClassSet Card =
Tw.Bg.White + Tw.Rounded.Lg + Tw.Shadow.Md + Tw.P._4 + Tw.Border + Tw.BorderColor.Slate._200;
public static readonly ClassSet ButtonPrimary =
Tw.Px._4 + Tw.Py._2 + Tw.Bg.Blue._600 + Tw.Text.White + Tw.Rounded.Md +
Tw.Hover.Bg.Blue._700 + Tw.Transition.Colors;
}- Full Tailwind Scale: Includes all standard spacing, sizing, colors, typography, borders, effects, and layout utilities.
- Arbitrary Values: First-class support for escape hatches like
Tw.W["37px"]orTw.GridCols["1fr_500px"]. - Raw Escape Hatch:
Tw.Raw("any-custom-class")ensures you are never blocked by the library. - Source Generated: Utilities are generated based on a JSON definition and your own CSS theme, ensuring the library stays lightweight.
- Blazor Integration: Works seamlessly with any Blazor component. Just use
@(style)in yourclassattribute.
BlazorTw uses a Roslyn Source Generator to emit readonly record struct tokens for every Tailwind utility, including all variant combinations. When you use the + operator, it efficiently concatenates these into a ClassSet, which implicitly converts to a string for use in your HTML.
Because every variant token (e.g., Tw.Hover.Bg.Blue._500) is a static field containing the literal string "hover:bg-blue-500", Tailwind's content scanner automatically detects all used classes — no safelisting required.
Tailwind CLI needs to scan your generated C# files to include the used classes in your final CSS bundle.
- Enable generated file emission and run Tailwind after compilation:
<!-- YourProject.csproj --> <PropertyGroup> <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles> </PropertyGroup>
- Add
@sourcedirectives to yourapp.css:@import "tailwindcss"; @source "../../BlazorTw.Core/**/*.cs"; @source "../../BlazorTw.Core/obj/**/*.g.cs"; @source "../obj/**/*.g.cs"; // If u have a theme defined and generated own files. @source "../Components/**/*.razor";
- Run the Tailwind CLI after compile so generated files exist on disk:
<Target Name="TailwindBuild" AfterTargets="Compile"> <Exec Command="npx @tailwindcss/cli -i ./Styles/app.css -o ./wwwroot/app.css" /> </Target>
MIT © Pascal Vorwerk