Custom Themes
The theme system is built on CSS variables defined in globals.css. Both Tailwind utilities and
shadcn/ui components reference these variables, so changing a few values updates the entire UI.
Theme variables
shadcn/ui expects a set of named CSS variables for colors, radii, and spacing. They live under
:root for light mode and .dark for dark mode.
/* app/globals.css */
:root {
--background: oklch(0.99 0.00 0);
--foreground: oklch(0.13 0.00 0);
--primary: oklch(0.55 0.18 260);
--primary-foreground: oklch(0.98 0.00 0);
--muted: oklch(0.95 0.01 260);
--muted-foreground: oklch(0.50 0.02 260);
--border: oklch(0.90 0.01 260);
--radius: 0.5rem;
}
.dark {
--background: oklch(0.13 0.02 260);
--foreground: oklch(0.95 0.00 0);
--primary: oklch(0.65 0.18 260);
--primary-foreground: oklch(0.13 0.00 0);
--muted: oklch(0.20 0.02 260);
--muted-foreground: oklch(0.65 0.02 260);
--border: oklch(0.25 0.02 260);
}
Using theme colors
Tailwind maps these variables to utility classes automatically:
<div className="bg-background text-foreground">
<p className="text-muted-foreground">Subtle text</p>
<button className="bg-primary text-primary-foreground">Action</button>
</div>
Dark mode
Dark mode is toggled by adding the .dark class to the <html> element. Use a theme provider
component to manage the toggle.
import { ThemeProvider } from "next-themes";
export default function RootLayout({ children }) {
return (
<html suppressHydrationWarning>
<body>
<ThemeProvider attribute="class" defaultTheme="system">
{children}
</ThemeProvider>
</body>
</html>
);
}
Creating a brand theme
To create a brand-specific theme, override the CSS variables with your brand palette.
| Variable | Role | Example (OKLCH) |
|---|---|---|
--primary | Main brand color | oklch(0.60 0.22 145) |
--primary-foreground | Text on primary | oklch(0.98 0.00 0) |
--accent | Secondary brand color | oklch(0.70 0.14 200) |
--destructive | Error / danger actions | oklch(0.55 0.22 25) |
OKLCH tips
- Adjust L (lightness) to create lighter/darker shades of the same hue.
- Keep C (chroma) under 0.25 for most UI surfaces; high chroma is best for accents.
- Use a tool like oklch.com to pick values visually.