Using DaisyUI Colors for Dark Mode: Semantic Variables and Theme Configuration

DaisyUI v5 semantic color utilities automatically adapt to light and dark themes through CSS variables, eliminating the need for dark: modifiers in your markup.

DaisyUI v5 (saadeghi/daisyui) revolutionizes dark mode implementation by using semantic color names that resolve to different values based on the active theme. Instead of duplicating classes with dark: prefixes, you use a single set of utilities like bg-primary or text-base-content that automatically switch values when the theme changes.

How Semantic Colors Work in DaisyUI

DaisyUI generates semantic color utilities backed by CSS variables defined in packages/daisyui/functions/variables.js. Each color name—such as primary, base-100, or neutral—maps to a CSS custom property like --color-primary or --color-base-100.

When you apply a utility class like bg-primary or text-base-content, the browser references these variables. As the active theme switches from light to dark, the underlying variable values update automatically, rendering the appropriate color without changing your HTML classes.

Enabling Automatic Dark Mode Detection

The default DaisyUI configuration enables seamless dark mode through the --prefersdark flag. In packages/daisyui/functions/themePlugin.js, this flag triggers the addition of a @media (prefers-color-scheme: dark) rule that applies the dark theme's variables to the appropriate root element.

Configure your themes in your CSS file:

@plugin "daisyui" {
  themes: light --default, dark --prefersdark;
}
  • light --default sets the light theme as the initial appearance
  • dark --prefersdark designates the dark theme as the fallback when the user's OS prefers dark color schemes

Practical Implementation Examples

Basic Usage Without Dark Prefixes

Because colors are tied to CSS variables, you never duplicate class names for light and dark variants:

<div class="p-10 bg-base-200 rounded-2xl">
  <div class="p-6 bg-base-100 border-2 border-base-300 text-base-content rounded-lg">
    This text adapts automatically: dark on light backgrounds, light on dark backgrounds.
  </div>
</div>

Explicit Theme Selection

Force a specific theme using the data-theme attribute:

<html data-theme="dark">
  <button class="btn btn-primary">Primary button</button>
</html>

Custom Dark Themes

Create custom dark themes by specifying them in your configuration:

@plugin "daisyui" {
  themes: winter --default, night --prefersdark;
}

When the night theme is active, all semantic utilities automatically resolve to that theme's color values.

Overriding Colors in Dark Mode

Customize specific colors for your dark theme using the theme override syntax:

@plugin "daisyui" {
  themes: light --default, dark --prefersdark;
}
@plugin "daisyui/theme" {
  name: "dark";
  "primary": "#0ea5e9";
}

This merges your custom primary color with the built-in dark theme, as handled by the merge logic in packages/daisyui/functions/themePlugin.js.

Using Opacity with Semantic Colors

Opacity modifiers work transparently across both themes:

<div class="bg-primary/50">50% opaque primary background</div>

Creating Custom Dark Themes

When building custom themes, add them to the themes list and flag them with --prefersdark to enable automatic OS detection. The plugin merges custom tokens with built-in themes, so you only override the specific colors you need.

For advanced use cases combining DaisyUI with Tailwind's dark: variant, configure a custom variant that targets your specific dark theme:

@plugin "daisyui" {
  themes: winter --default, night --prefersdark;
}
@custom-variant dark (&:where([data-theme=night], [data-theme=night] *));
<div class="p-10 dark:p-20">
  Padding doubles only when the night theme is active.
</div>

Summary

  • DaisyUI v5 uses semantic color names (primary, base-100, base-content) backed by CSS variables defined in packages/daisyui/functions/variables.js
  • The --prefersdark flag in your theme configuration enables automatic dark mode detection via prefers-color-scheme media queries, implemented in packages/daisyui/functions/themePlugin.js
  • No dark: prefixes are required because utilities like bg-primary automatically resolve to theme-specific values
  • Custom themes merge with built-in themes, allowing targeted color overrides without redefining the entire palette
  • Opacity modifiers (e.g., bg-primary/50) work consistently across light and dark themes

Frequently Asked Questions

Do I need to use dark: prefixes with DaisyUI?

No. DaisyUI's semantic color system eliminates the need for dark: prefixes because each utility class references CSS variables that change values based on the active theme. When the dark theme is active, bg-base-100 automatically renders a dark background, and text-base-content automatically renders light text.

How does DaisyUI detect the user's OS dark mode preference?

DaisyUI detects OS preferences through the --prefersdark flag in your theme configuration. According to the packages/daisyui/functions/themePlugin.js implementation, this flag generates a @media (prefers-color-scheme: dark) rule that applies the dark theme's CSS variables to :root when the user's system is set to dark mode.

Can I create a custom dark theme with specific brand colors?

Yes. Define your custom theme using the @plugin "daisyui/theme" syntax and specify the colors you want to override. The plugin merges your custom tokens with the built-in theme structure, so you only need to define the specific color values you want to change, such as setting "primary": "#0ea5e9" for a custom dark primary color.

What is the difference between base-100 and base-content?

base-100 represents the page background color (the dominant surface), while base-content represents the text color designed to contrast against that background. In a light theme, base-100 is typically white or light gray and base-content is dark gray or black. In a dark theme, these values invert automatically, with base-100 becoming dark and base-content becoming light.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →