Tailwind ships with a carefully designed default theme, but real projects need custom branding. Tailwind makes it straightforward to extend or override every design token.
Tailwind CSS 4: Theme Configuration
In Tailwind CSS 4, theme customization is done directly in your CSS using the @theme directive instead of a JavaScript config file:
These tokens immediately generate utilities like bg-brand, text-brand-light, font-sans, rounded-card, and w-128.
Custom Color Palette
Define a full color scale for your brand:
Now use these like any built-in color:
Custom Fonts
Register font families in @theme and load them with @font-face or a service like Google Fonts:
@theme {
--font-sans: "Inter", ui-sans-serif, system-ui, sans-serif;
--font-display: "Cal Sans", "Inter", sans-serif;
}<h1 class="font-display text-4xl font-bold">Welcome Back</h1>
<p class="font-sans text-gray-600">Here is your dashboard overview.</p>Dark Mode
Tailwind supports dark mode via a CSS variant. In Tailwind CSS 4, configure it with @custom-variant:
@custom-variant dark (&:where(.dark, .dark *));This makes the dark: variant apply when the dark class is on an ancestor element (typically <html>).
Toggling the Dark Class
function ThemeToggle() {
const toggle = () => {
const isDark = document.documentElement.classList.toggle("dark");
localStorage.setItem("theme", isDark ? "dark" : "light");
};
return (
<button onClick={toggle} class="p-2 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-700">
<span class="dark:hidden">Moon Icon</span>
<span class="hidden dark:inline">Sun Icon</span>
</button>
);
}Preventing Flash of Wrong Theme
Add a blocking script in <head> that reads the stored preference before the page renders:
Styling for Dark Mode
Apply dark: variants alongside your default styles:
CSS Variables for Dynamic Theming
CSS variables let you change themes at runtime without recompiling CSS. Define variables and reference them in @theme:
<div class="bg-ui-bg text-ui-text">
<a href="#" class="text-ui-accent hover:underline">Learn more</a>
</div>This technique also works for multi-brand theming — swap variables based on a class or data attribute: