Theming Guide
Vultra UI uses CSS custom properties for theming. This guide covers advanced patterns beyond the basics.
Anatomy of a Theme
Every theme is a CSS file that redefines the same variables:
/* Custom theme: brand.css */
@import "@vultra/tokens/base";
:root {
--ui-background: oklch(0.98 0.01 240);
--ui-foreground: oklch(0.2 0.02 240);
--ui-primary: oklch(0.55 0.2 265);
--ui-primary-foreground: oklch(1 0 0);
--ui-radius: 0.75rem;
} Import it instead of the base theme:
/* app.css */
@import "@vultra/tokens/brand.css"; /* your custom theme */ Dark Mode with Two Themes
Stack themes with a class toggle:
/* app.css */
@import "@vultra/tokens/base";
html.dark {
--ui-background: oklch(0.15 0.01 240);
--ui-foreground: oklch(0.95 0 0);
--ui-primary: oklch(0.7 0.15 265);
--ui-card: oklch(0.2 0.01 240);
} // Theme toggle
const theme = localStorage.getItem('theme') ?? 'light';
document.documentElement.classList.toggle('dark', theme === 'dark');
function toggle() {
const dark = document.documentElement.classList.toggle('dark');
localStorage.setItem('theme', dark ? 'dark' : 'light');
} All Variables
| Variable | Purpose |
|---|---|
--ui-background | Page background |
--ui-foreground | Default text |
--ui-card | Card surface |
--ui-card-foreground | Card text |
--ui-primary | Primary action color |
--ui-primary-foreground | Text on primary |
--ui-secondary | Secondary surface |
--ui-muted | Muted surface |
--ui-muted-foreground | Muted text |
--ui-accent | Accent color |
--ui-border | Border color |
--ui-ring | Focus ring |
--ui-radius | Border radius |
--ui-shadow-sm/md/lg/xl | Shadow levels |
Building a Custom Theme
- Start from a base — copy
@vultra/tokens/baseor any theme - Override semantic colors — keep the variable names, change values
- Test contrast — foreground on background, primary on primary-foreground
- Export — publish as
@your-brand/tokensfor your team
Theme Recipes
Minimal
:root {
--ui-radius: 0.25rem;
--ui-background: oklch(0.99 0 0);
--ui-primary: oklch(0.25 0 0);
--ui-primary-foreground: oklch(0.99 0 0);
--ui-border: oklch(0.9 0 0);
} Warm
:root {
--ui-background: oklch(0.98 0.01 80);
--ui-primary: oklch(0.6 0.15 45);
--ui-border: oklch(0.9 0.02 80);
} High Contrast
:root {
--ui-background: oklch(1 0 0);
--ui-foreground: oklch(0 0 0);
--ui-primary: oklch(0 0 0);
--ui-primary-foreground: oklch(1 0 0);
--ui-radius: 0;
}