Skip to content
daisyBlazor

CSS preset

A Tailwind CSS v4 + daisyUI v5 preset ships inside the DaisyBlazor.Components NuGet package. Nothing comes from npm: the preset bundles daisyUI itself, and the package can run the Tailwind standalone CLI for you.
Styles/main.css
One import.
@import "tailwindcss";
@import "…/preset.css";
daisyUI 37 themes safelist

No Node, no npm.

What the preset does

The preset does three jobs:

  1. Enables daisyUI: a vendored copy of daisyUI's standalone bundle, so no npm install daisyui.
  2. Registers themes: the two neutral DaisyBlazor defaults, daisyblazor (light, the default) and daisyblazor-dark (dark, prefers-color-scheme: dark), plus all 35 built-in daisyUI v5 themes (light, dark, cupcake, synthwave, dracula, nord, business, night, dim, sunset, abyss, silk, …).
  3. Safelists every class the components emit so they survive Tailwind's purge (see below).

Wiring it into your app

On every build, the package copies the preset into your project's obj/daisyblazor/ folder. Turn on the CSS build in your .csproj:

MyApp.csproj
<PropertyGroup>
  <DaisyBlazorBuildCss>true</DaisyBlazorBuildCss>
</PropertyGroup>

and write Styles/main.css:

Styles/main.css
@import "tailwindcss";
@import "../obj/daisyblazor/preset.css";

/* Your own markup. The packaged components need no glob: the preset safelists their classes. */
@source "./Components/**/*.{razor,cs}";

Then every dotnet build runs this:

  • Preset copied to obj/daisyblazor/
  • Tailwind CLI compiles Styles/main.css
  • wwwroot/css/app.css

The first build downloads the pinned Tailwind CSS standalone CLI into a per-user cache (~/.local/share/daisyblazor/tailwind/<version>/ on Linux, %LOCALAPPDATA%\daisyblazor\tailwind\<version>\ on Windows); later builds reuse it. Link the output in your host page. The dotnet new daisyblazor template wires all of this for you (see Getting started).

MSBuild properties

MSBuild propertyDefaultPurpose
DaisyBlazorBuildCssfalseCompile the CSS on build with the Tailwind standalone CLI.
DaisyBlazorCssInputStyles/main.cssTailwind entry stylesheet.
DaisyBlazorCssOutputwwwroot/css/app.cssCompiled stylesheet.
DaisyBlazorTailwindVersionthe version the package was tested withTailwind CLI release to download.
DaisyBlazorTailwindPaththe cached downloadUse your own Tailwind binary (offline builds, musl Linux).
DaisyBlazorStylesDirobj/daisyblazor/Where the preset is copied.
DaisyBlazorDaisyUIVersionempty (the vendored daisyUI)daisyUI release to download (into the same per-user cache) and copy instead of the vendored bundles, e.g. 5.5.20.

The CSS build is incremental: it is skipped when DaisyBlazorCssInput, the preset and the DaisyBlazorCssSource items (by default every .razor, .cs, .cshtml, .html and .css file in the project) are older than DaisyBlazorCssOutput. If a @source glob scans files outside the project, add them as <DaisyBlazorCssSource Include="../Shared/**/*.razor" /> so a change there recompiles.

If the Tailwind CLI download fails (offline, unknown version) and DaisyBlazorCssOutput already exists, the build keeps that file and warns instead of failing; with no existing output it fails with a message naming the ways out (DaisyBlazorTailwindPath, or DaisyBlazorBuildCss=false with a committed CSS file).

Already building CSS with the npm tailwindcss CLI or Vite? Leave DaisyBlazorBuildCss off and just import obj/daisyblazor/preset.css from your stylesheet: the copy happens either way.

Only the DaisyBlazor themes

The 35 built-in themes add weight. If you only need daisyblazor / daisyblazor-dark (optionally plus your own theme blocks), import preset-core.css instead. It is identical apart from the theme list:

Styles/main.css
@import "tailwindcss";
@import "../obj/daisyblazor/preset-core.css";

Only your own themes

If you declare all your themes yourself, import just safelist.css and enable daisyUI with your own theme list, using the bundles the package copied next to it:

Styles/main.css
@import "tailwindcss";
@import "../obj/daisyblazor/safelist.css";

@plugin "../obj/daisyblazor/daisyui.mjs" {
    themes: mybrand --default, mybrand-dark --prefersdark;
}
@plugin "../obj/daisyblazor/daisyui-theme.mjs" {
    name: "mybrand";
    /* --color-primary: …; etc. */
}

Source globs

Both forms of @source glob work on Tailwind v4.1+ (verified on 4.3): a brace group such as @source "./Components/**/*.{razor,cs}";, or one line per extension. The template uses one line per extension, which also works on older 4.0.x builds.

The comment-scanning gotcha

Tailwind v4 scans for @source and @import tokens even inside CSS comments. If you put a literal @source "..." or @import "..." at-rule inside a /* … */ block as documentation, Tailwind will try to resolve it and can fail the build (or pull in unexpected files).

The class safelist

The NuGet package ships compiled components, not their .razor/.cs sources, so Tailwind in your app cannot scan them. safelist.css therefore force-generates, with @source inline(...):

  • the classes composed dynamically in C# (colour/size variants such as btn-primary, alert-soft, loading-spinner, the 12-column grid/span/gap utilities, mask-*, tooltip-*, …), and
  • every literal class used in the component markup (menu, modal, navbar, drawer, …). This block is generated from the component sources by scripts/gen-styles.mjs, and CI fails if it goes stale.

So you do not need any @source glob pointing at the DaisyBlazor packages.

The Material Symbols webfont

The Icon component and the Icons.Material.* constants render Material Symbols ligatures: the font turns a name like check_circle into the glyph. The preset can't bundle a webfont, so load it once in your host page (App.razor or index.html):

App.razor
<link rel="stylesheet"
      href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined" />

Without it, icons render as their literal ligature text.

The heading font

Components that render a title (the Dialog header, for one) add the font-heading class. safelist.css ships a default @utility font-heading that reads --font-heading and falls back to the inherited body font, so headings look right with no setup. To give them their own face, define the variable after the preset import:

Styles/main.css
@import "tailwindcss";
@import "../obj/daisyblazor/preset.css";

@theme {
    --font-heading: "Plus Jakarta Sans", "Helvetica Neue", sans-serif;
}

Need more than a font family (weight, letter-spacing)? Redeclare @utility font-heading { … } after the import; Tailwind emits both rules and yours, coming later, wins.

See also: Getting started for the full install walkthrough, and Theming for the themes the preset registers and how to switch or extend them.

Something went wrong while running the docs. Reload