DaisyUI Colors and Theming: Complete Guide to Custom Themes
DaisyUI implements a zero-runtime theming system by injecting CSS custom properties into Tailwind's base layer via the themePlugin.js file, allowing themes to switch instantly by changing the data-theme attribute.
DaisyUI is a popular Tailwind CSS component library that provides a robust theming architecture built entirely on CSS variables. Understanding how DaisyUI colors and theming work enables developers to create custom color palettes, support dark mode, and switch themes at runtime without JavaScript overhead. This guide examines the actual source code in the saadeghi/daisyui repository to explain how the theming engine processes configurations and generates the CSS custom properties that power your UI.
How DaisyUI Theming Works Under the Hood
DaisyUI's theming system consists of four interconnected components that transform your tailwind.config.js settings into usable CSS variables.
Variable Mapping in variables.js
At the core of the system is variables.js, which exports a static object mapping semantic token names to CSS variable references. This file establishes the contract between DaisyUI's utility classes and the underlying CSS custom properties.
For example, the token primary maps to var(--color-primary), while base-100 maps to var(--color-base-100). This abstraction allows components to reference semantic colors rather than hardcoded values.
Theme Generation Pipeline
The generateThemes.js file processes your configuration's themes array to create a comprehensive allThemes object. Each theme is structured as a JavaScript object where keys match the variable map from variables.js.
Simultaneously, generateThemeFiles.js creates standalone CSS files for each theme, which are used for CDN builds and static distribution.
Plugin Injection via themePlugin.js
The critical integration happens in themePlugin.js, which uses Tailwind's plugin.withOptions API. When Tailwind starts, this plugin:
- Receives your theme configuration from
tailwind.config.js - Merges custom themes with built-in presets
- Constructs CSS selectors targeting
:root[data-theme="name"]and theme-controller inputs - Registers base styles using
addBase(baseStyles)
The plugin generates a baseStyles object that maps selectors to CSS variable declarations and color-scheme properties. If a theme is marked as default, the selector includes :where(:root) to ensure fallback behavior.
Runtime Activation
Users toggle themes by setting the data-theme attribute on the root element or using the built-in .theme-controller checkbox component. Because the variables are defined on the :root selector, they cascade naturally to all components, enabling instant theme switching without JavaScript re-renders.
Configuring Custom Themes in tailwind.config.js
To define a custom theme, add an object to the daisyui.themes array in your Tailwind configuration.
// tailwind.config.js
module.exports = {
content: ["./src/**/*.{html,js,tsx}"],
plugins: [require("daisyui")],
daisyui: {
themes: [
{
"my-theme": {
primary: "#4f46e5",
secondary: "#ec4899",
accent: "#f59e0b",
neutral: "#374151",
"base-100": "#ffffff",
"color-scheme": "dark",
},
},
"light",
"dark",
],
},
}
Each property in your theme object corresponds to a CSS variable. The "color-scheme" property optionally sets the color-scheme CSS property for native form controls and scrollbars.
Using Themes at Runtime
Apply themes to your application using the data-theme attribute or the theme-controller component.
<!-- Apply theme to the entire page -->
<html data-theme="my-theme">
<body class="bg-base-100 text-base-content">
<button class="btn btn-primary">Primary Action</button>
<!-- Theme toggle controller -->
<input type="checkbox" class="theme-controller" value="my-theme" checked />
</body>
</html>
When the data-theme attribute value changes, DaisyUI utilities such as bg-primary and text-secondary automatically resolve to the new theme's CSS variables.
Implementing Dark Mode with prefers-color-scheme
DaisyUI supports automatic dark mode detection via the prefersdark option. When enabled in tailwind.config.js, the plugin injects a media query block that activates the theme when the user prefers dark mode.
// tailwind.config.js
module.exports = {
daisyui: {
themes: [
{
"my-theme": {
primary: "#4f46e5",
secondary: "#ec4899",
// ... other tokens
},
prefersdark: true, // Enables dark mode media query
},
],
},
}
This generates the following CSS in the output:
@media (prefers-color-scheme: dark) {
:root:not([data-theme]) {
color-scheme: dark;
--color-primary: #4f46e5;
/* Additional theme variables */
}
}
The :root:not([data-theme]) selector ensures the media query only applies when no explicit theme is set via the data-theme attribute.
Referencing DaisyUI Colors in Custom CSS
Because DaisyUI defines variables on the root element, you can reference them in your own stylesheets for consistency with the active theme.
.my-card {
background-color: var(--color-base-100);
border: 1px solid var(--color-primary);
color: var(--color-base-content);
}
This approach ensures your custom components automatically adapt when users switch themes, maintaining visual consistency with DaisyUI's utility classes.
Summary
- DaisyUI generates themes through
variables.js,generateThemes.js, andthemePlugin.js, creating a zero-runtime CSS variable system. - The
themePlugin.jsfile uses Tailwind'saddBaseto inject CSS custom properties into:rootselectors based on yourtailwind.config.jsconfiguration. - Custom themes are defined as objects in the
daisyui.themesarray, mapping semantic tokens likeprimaryandbase-100to hex colors. - Set
data-themeattributes or use.theme-controllerinputs to switch themes instantly without JavaScript. - Enable
prefersdark: trueto generate@media (prefers-color-scheme: dark)blocks for automatic dark mode support. - Access theme colors anywhere using
var(--color-{token})syntax for custom CSS integration.
Frequently Asked Questions
How do I create a completely custom DaisyUI theme?
Define your theme as an object in the daisyui.themes array within tailwind.config.js. The object keys should match DaisyUI's semantic tokens (primary, secondary, accent, neutral, base-100, etc.) with hex color values. The theme engine in generateThemes.js processes these values and themePlugin.js injects them as CSS variables.
Does DaisyUI support automatic dark mode detection?
Yes. Set prefersdark: true on your theme configuration in tailwind.config.js. When enabled, themePlugin.js generates a media query block that applies your theme variables when the user's system prefers dark mode, using the :root:not([data-theme]) selector to avoid overriding explicit theme selections.
How does the theme-controller component work?
The theme-controller is a CSS-only toggle mechanism using an <input type="checkbox"> with the class theme-controller. When checked, it sets the data-theme attribute on the root element to the input's value. DaisyUI's generated CSS targets [data-theme="value"] selectors, causing the CSS variables to update instantly without JavaScript execution.
Can I use DaisyUI color variables in my own CSS?
Yes. DaisyUI exposes all theme colors as CSS custom properties in the format --color-{token} (e.g., --color-primary, --color-base-100). These are defined on the :root selector, making them globally available. Reference them using var(--color-primary) in your custom stylesheets to maintain consistency with the active theme.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →