What the preset does
The preset does three jobs:
- Enables daisyUI: a vendored copy of daisyUI's standalone bundle, so no
npm install daisyui. - Registers themes: the two neutral DaisyBlazor defaults,
daisyblazor(light, the default) anddaisyblazor-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, …). - Safelists every class the components emit so they survive Tailwind's purge (see below).
pointer-events: none to .btn[aria-disabled=true] (5.5 left aria-disabled
buttons alone). Buttons you keep clickable while marked aria-disabled stop
receiving clicks and hover: move the explanation to a wrapper, or re-enable them with your own rule after the preset import,
e.g. .btn.btn-explain[aria-disabled="true"] { pointer-events: auto; }. See Button.
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:
<PropertyGroup>
<DaisyBlazorBuildCss>true</DaisyBlazorBuildCss>
</PropertyGroup>and write 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 property | Default | Purpose |
|---|---|---|
DaisyBlazorBuildCss | false | Compile the CSS on build with the Tailwind standalone CLI. |
DaisyBlazorCssInput | Styles/main.css | Tailwind entry stylesheet. |
DaisyBlazorCssOutput | wwwroot/css/app.css | Compiled stylesheet. |
DaisyBlazorTailwindVersion | the version the package was tested with | Tailwind CLI release to download. |
DaisyBlazorTailwindPath | the cached download | Use your own Tailwind binary (offline builds, musl Linux). |
DaisyBlazorStylesDir | obj/daisyblazor/ | Where the preset is copied. |
DaisyBlazorDaisyUIVersion | empty (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:
@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:
@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).
source "<path>" without the leading @) and tell the reader to turn it into a real at-rule.
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 byscripts/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):
<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:
@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.