Customization
Learn how Preline Themes work, how to apply a theme, and how to customize semantic tokens for consistent UI across components.
A theme is a set of design values that defines the visual identity of a product and keeps it consistent across all UI components.
Preline Themes let you customize the look of your application by overriding semantic design tokens implemented as CSS variables like --primary, --background, and --border. Change your brand colors once, and every component updates automatically — no need to hunt down utility classes.
In Tailwind terms, these low-level design decisions are often called design tokens, and their values are typically stored in Tailwind theme variables. Preline exposes them as additional semantic CSS variables so components can read them consistently.
While themes focus primarily on colors, they're fully extensible at the CSS level. Add your own CSS variables for spacing, typography, or anything else and combine them with Tailwind's theme settings (fonts, shadows, etc.) for deeper customization.
What Preline Themes Do
What Preline Themes Don't Do
For Tailwind's theming system (@theme, breakpoints, spacing, etc.), see the official
Tailwind CSS theming docs.
Themes are defaulted to all Preline content but they are optional. You may use full utility classes instead. All components, examples and templates comes with Copy Utility Classes option.
Preline Themes are loaded from your CSS entry file (for example main.css), not directly from HTML.
Import the base theme once, then optionally import any predefined themes you want to support.
@import "tailwindcss";
/* Base theme tokens + mappings */
@import "./themes/theme.css";
/* Optional: predefined themes (import only what you need) */
@import "./themes/harvest.css";
@import "./themes/retro.css";
@import "./themes/ocean.css";
@import "./themes/bubblegum.css";
@import "./themes/autumn.css";
@import "./themes/moon.css";
@import "./themes/cashmere.css";
@import "./themes/olive.css";
Preline ships with several premade themes you can use out of the box. Themes are not limited to “brand” colors, they also include tuned neutral palettes (backgrounds, surfaces, borders, etc.) for a cohesive look. If needed, you can extend a theme beyond colors (for example typography and other design tokens).
| Theme | Description |
|---|---|
theme.css
|
Default theme with a clear, high-contrast blue primary and neutral surfaces. Great for web applications and enterprise products. |
harvest.css
|
A warm, low-contrast, eye-friendly theme that feels stable, natural, and professional, designed for long working sessions without fatigue. |
retro.css
|
High-contrast magenta accents with sharp edges, creating a bold, nostalgic, and expressive look. |
ocean.css
|
Cool teal tones with balanced contrast, delivering a clean, calm, and refreshing visual feel. |
autumn.css
|
Rich amber and golden tones with warm contrast, creating a cozy, grounded, and confident appearance. |
moon.css
|
Deep navy and muted blue tones with low saturation, producing a calm, focused, and night-friendly interface. |
bubblegum.css
|
Bright pink accents with lively contrast, giving a playful, energetic, and expressive visual style. |
cashmere.css
|
Warm dusty rose and soft brown undertones with low contrast, creating a calm, refined, and quietly premium appearance. |
olive.css
|
Muted olive-green tones with warm undertones and low contrast, creating a grounded, natural, and quietly confident look. |
To activate a predefined theme, add to your CSS file and set data-theme on <html>.
@import "tailwindcss";
/* Activating the Harvest theme */
@import "./themes/theme.css";
@import "./themes/harvest.css";
<html data-theme="theme-harvest">
...
</html>
These are the core semantic tokens (CSS custom properties) that Preline components use. Override them to customize colors, surfaces, and component styles across your application.
| Group | Tokens | Used for |
|---|---|---|
| Brand |
--primary, --primary-*
|
Primary actions (buttons, links) |
| Secondary |
--secondary, --secondary-*
|
Secondary emphasis |
| Muted |
--muted, --muted-*
|
Muted/subdued elements |
| Destructive |
--destructive, --destructive-*
|
Destructive/danger actions |
| Background |
--background, --background-*
|
App surfaces |
| Foreground |
--foreground, --foreground-*
|
Default typography colors |
| Inverse |
--inverse
|
Inverted color scheme |
| Border |
--border
|
Default border color |
| Border line |
--border-line-*
|
Border colors for different shades of gray |
| Layer |
--layer, --layer-*
|
Layered elements e.g. white buttons on white panel |
| Surface |
--surface, --surface-*
|
Elevated surfaces |
| Navbar |
--navbar, --navbar-*
|
Navigation bar background, border, divider |
| Navbar nav |
--navbar-nav-*
|
Navigation bar items (foreground, hover, active) |
| Sidebar |
--sidebar, --sidebar-*
|
Sidebar background, border, divider |
| Sidebar nav |
--sidebar-nav-*
|
Sidebar items (foreground, hover, active) |
| Card |
--card, --card-*
|
Card component (border, divider, header, footer) |
| Dropdown |
--dropdown, --dropdown-*
|
Dropdown menus (items, hover, active) |
| Select |
--select, --select-*
|
Select component (items, hover, active) |
| Overlay |
--overlay, --overlay-*
|
Modal/overlay backgrounds |
| Popover |
--popover, --popover-*
|
Popover component |
| Tooltip |
--tooltip, --tooltip-*
|
Tooltip component |
| Table |
--table-border
|
Table borders |
| Switch |
--switch
|
Switch/toggle component |
| Footer |
--footer, --footer-*
|
Footer component |
| Scrollbar |
--scrollbar-*
|
Custom scrollbar (track, thumb) |
| Chart |
--chart-*
|
Chart colors (Apexcharts) |
| Map |
--map-colors-*
|
Map colors (jsvectormap) |
Border tokens use the --*-line-* scale (and utilities like border-line-1, border-card-line, …) instead of names like border-border or border-card-border, which can look confusing. This keeps border utilities consistent and readable across components.
Preline themes expose multiple components' "presets" (e.g. navbar, sidebar etc.) so components can offer different ready-made looks (e.g. white, slightly tinted, higher-contrast) without inventing new token names per component.
| Pattern Example | Meaning |
|---|---|
--navbar-* |
Default navbar preset (base style) |
--navbar-1-* |
Variant 1 preset (typically a subtle/tinted surface) |
--navbar-2-* |
Variant 2 preset (typically a stronger tint or different border behavior) |
* (no suffix) |
Background/surface color of the component |
*-border / *-line |
Border color (or transparency) for the component container |
*-divider |
Divider lines inside the component |
*-nav-* |
Nav item colors (foreground, hover, focus, active) |
*-nav-list-divider |
Divider used in nav dropdown/list layouts |
Navbar --navbar-* is just one example, other component token groups may include similar preset variants.
Preline maps semantic CSS variables (like --primary) into Tailwind color utilities via @theme inline.
This is the full mapping available for customization (organized by component type and state variants).
@theme inline {
--color-background: var(--background);
--color-background-1: var(--background-1);
--color-background-2: var(--background-2);
--color-plain: var(--background-plain);
--color-foreground: var(--foreground);
--color-foreground-inverse: var(--foreground-inverse);
--color-inverse: var(--inverse);
--color-border: var(--border);
--color-line-inverse: var(--border-line-inverse);
--color-line-1: var(--border-line-1);
--color-line-2: var(--border-line-2);
--color-line-3: var(--border-line-3);
--color-line-4: var(--border-line-4);
--color-line-5: var(--border-line-5);
--color-line-6: var(--border-line-6);
--color-line-7: var(--border-line-7);
--color-line-8: var(--border-line-8);
--color-primary-50: var(--primary-50);
--color-primary-100: var(--primary-100);
--color-primary-200: var(--primary-200);
--color-primary-300: var(--primary-300);
--color-primary-400: var(--primary-400);
--color-primary-500: var(--primary-500);
--color-primary-600: var(--primary-600);
--color-primary-700: var(--primary-700);
--color-primary-800: var(--primary-800);
--color-primary-900: var(--primary-900);
--color-primary-950: var(--primary-950);
--color-primary: var(--primary);
--color-primary-line: var(--primary-line);
--color-primary-foreground: var(--primary-foreground);
--color-primary-hover: var(--primary-hover);
--color-primary-focus: var(--primary-focus);
--color-primary-active: var(--primary-active);
--color-primary-checked: var(--primary-checked);
--color-secondary: var(--secondary);
--color-secondary-line: var(--secondary-line);
--color-secondary-foreground: var(--secondary-foreground);
--color-secondary-hover: var(--secondary-hover);
--color-secondary-focus: var(--secondary-focus);
--color-secondary-active: var(--secondary-active);
--color-layer: var(--layer);
--color-layer-line: var(--layer-line);
--color-layer-foreground: var(--layer-foreground);
--color-layer-hover: var(--layer-hover);
--color-layer-focus: var(--layer-focus);
--color-layer-active: var(--layer-active);
--color-surface: var(--surface);
--color-surface-1: var(--surface-1);
--color-surface-2: var(--surface-2);
--color-surface-3: var(--surface-3);
--color-surface-4: var(--surface-4);
--color-surface-5: var(--surface-5);
--color-surface-line: var(--surface-line);
--color-surface-foreground: var(--surface-foreground);
--color-surface-hover: var(--surface-hover);
--color-surface-focus: var(--surface-focus);
--color-surface-active: var(--surface-active);
--color-muted: var(--muted);
--color-muted-foreground: var(--muted-foreground);
--color-muted-foreground-1: var(--muted-foreground-1);
--color-muted-foreground-2: var(--muted-foreground-2);
--color-muted-hover: var(--muted-hover);
--color-muted-focus: var(--muted-focus);
--color-muted-active: var(--muted-active);
--color-destructive: var(--destructive);
--color-destructive-foreground: var(--destructive-foreground);
--color-destructive-hover: var(--destructive-hover);
--color-destructive-focus: var(--destructive-focus);
--color-navbar: var(--navbar);
--color-navbar-line: var(--navbar-border);
--color-navbar-divider: var(--navbar-divider);
--color-navbar-nav-foreground: var(--navbar-nav-foreground);
--color-navbar-nav-hover: var(--navbar-nav-hover);
--color-navbar-nav-focus: var(--navbar-nav-focus);
--color-navbar-nav-active: var(--navbar-nav-active);
--color-navbar-nav-list-divider: var(--navbar-nav-list-divider);
--color-navbar-inverse: var(--navbar-inverse);
--color-navbar-1: var(--navbar-1);
--color-navbar-1-line: var(--navbar-1-border);
--color-navbar-1-divider: var(--navbar-1-divider);
--color-navbar-1-nav-foreground: var(--navbar-1-nav-foreground);
--color-navbar-1-nav-hover: var(--navbar-1-nav-hover);
--color-navbar-1-nav-focus: var(--navbar-1-nav-focus);
--color-navbar-1-nav-active: var(--navbar-1-nav-active);
--color-navbar-1-nav-list-divider: var(--navbar-1-nav-list-divider);
--color-navbar-2: var(--navbar-2);
--color-navbar-2-line: var(--navbar-2-border);
--color-navbar-2-divider: var(--navbar-2-divider);
--color-navbar-2-nav-foreground: var(--navbar-2-nav-foreground);
--color-navbar-2-nav-hover: var(--navbar-2-nav-hover);
--color-navbar-2-nav-focus: var(--navbar-2-nav-focus);
--color-navbar-2-nav-active: var(--navbar-2-nav-active);
--color-navbar-2-nav-list-divider: var(--navbar-2-nav-list-divider);
--color-sidebar: var(--sidebar);
--color-sidebar-line: var(--sidebar-border);
--color-sidebar-divider: var(--sidebar-divider);
--color-sidebar-nav-foreground: var(--sidebar-nav-foreground);
--color-sidebar-nav-hover: var(--sidebar-nav-hover);
--color-sidebar-nav-focus: var(--sidebar-nav-focus);
--color-sidebar-nav-active: var(--sidebar-nav-active);
--color-sidebar-nav-list-divider: var(--sidebar-nav-list-divider);
--color-sidebar-inverse: var(--sidebar-inverse);
--color-sidebar-1: var(--sidebar-1);
--color-sidebar-1-line: var(--sidebar-1-border);
--color-sidebar-1-divider: var(--sidebar-1-divider);
--color-sidebar-1-nav-foreground: var(--sidebar-1-nav-foreground);
--color-sidebar-1-nav-hover: var(--sidebar-1-nav-hover);
--color-sidebar-1-nav-focus: var(--sidebar-1-nav-focus);
--color-sidebar-1-nav-active: var(--sidebar-1-nav-active);
--color-sidebar-1-nav-list-divider: var(--sidebar-1-nav-list-divider);
--color-sidebar-2: var(--sidebar-2);
--color-sidebar-2-line: var(--sidebar-2-border);
--color-sidebar-2-divider: var(--sidebar-2-divider);
--color-sidebar-2-nav-foreground: var(--sidebar-2-nav-foreground);
--color-sidebar-2-nav-hover: var(--sidebar-2-nav-hover);
--color-sidebar-2-nav-focus: var(--sidebar-2-nav-focus);
--color-sidebar-2-nav-active: var(--sidebar-2-nav-active);
--color-sidebar-2-nav-list-divider: var(--sidebar-2-nav-list-divider);
--color-card: var(--card);
--color-card-line: var(--card-border);
--color-card-divider: var(--card-divider);
--color-card-header: var(--card-header);
--color-card-footer: var(--card-footer);
--color-card-inverse: var(--card-inverse);
--color-dropdown: var(--dropdown);
--color-dropdown-1: var(--dropdown-1);
--color-dropdown-line: var(--dropdown-border);
--color-dropdown-divider: var(--dropdown-divider);
--color-dropdown-header: var(--dropdown-header);
--color-dropdown-footer: var(--dropdown-footer);
--color-dropdown-item-foreground: var(--dropdown-item-foreground);
--color-dropdown-item-hover: var(--dropdown-item-hover);
--color-dropdown-item-focus: var(--dropdown-item-focus);
--color-dropdown-item-active: var(--dropdown-item-active);
--color-dropdown-inverse: var(--dropdown-inverse);
--color-select: var(--select);
--color-select-1: var(--select-1);
--color-select-line: var(--select-border);
--color-select-item-foreground: var(--select-item-foreground);
--color-select-item-hover: var(--select-item-hover);
--color-select-item-focus: var(--select-item-focus);
--color-select-item-active: var(--select-item-active);
--color-select-inverse: var(--select-inverse);
--color-overlay: var(--overlay);
--color-overlay-line: var(--overlay-border);
--color-overlay-divider: var(--overlay-divider);
--color-overlay-header: var(--overlay-header);
--color-overlay-footer: var(--overlay-footer);
--color-overlay-inverse: var(--overlay-inverse);
--color-popover: var(--popover);
--color-popover-line: var(--popover-border);
--color-tooltip: var(--tooltip);
--color-tooltip-foreground: var(--tooltip-foreground);
--color-tooltip-line: var(--tooltip-border);
--color-table-line: var(--table-border);
--color-switch: var(--switch);
--color-footer: var(--footer);
--color-footer-line: var(--footer-border);
--color-footer-inverse: var(--footer-inverse);
--color-scrollbar-track: var(--scrollbar-track);
--color-scrollbar-thumb: var(--scrollbar-thumb);
--color-scrollbar-track-inverse: var(--scrollbar-track-inverse);
--color-scrollbar-thumb-inverse: var(--scrollbar-thumb-inverse);
--color-chart-primary: var(--chart-primary);
--color-chart-1: var(--chart-1);
--color-chart-2: var(--chart-2);
--color-chart-3: var(--chart-3);
--color-chart-4: var(--chart-4);
--color-chart-5: var(--chart-5);
--color-chart-6: var(--chart-6);
--color-chart-7: var(--chart-7);
--color-chart-8: var(--chart-8);
--color-chart-9: var(--chart-9);
--color-chart-10: var(--chart-10);
}
These are the default semantic token values for light mode (:root) and dark mode (.dark), from the base theme.
Light mode
:root {
--background: var(--color-white);
--background-1: var(--color-gray-50);
--background-2: var(--color-gray-100);
--background-plain: var(--color-white);
--foreground: var(--color-gray-800);
--foreground-inverse: var(--color-white);
--inverse: var(--color-gray-800);
--border: var(--color-gray-200);
--border-line-inverse: var(--color-white);
--border-line-1: var(--color-gray-100);
--border-line-2: var(--color-gray-200);
--border-line-3: var(--color-gray-300);
--border-line-4: var(--color-gray-400);
--border-line-5: var(--color-gray-500);
--border-line-6: var(--color-gray-600);
--border-line-7: var(--color-gray-700);
--border-line-8: var(--color-gray-800);
--primary-50: var(--color-blue-50);
--primary-100: var(--color-blue-100);
--primary-200: var(--color-blue-200);
--primary-300: var(--color-blue-300);
--primary-400: var(--color-blue-400);
--primary-500: var(--color-blue-500);
--primary-600: var(--color-blue-600);
--primary-700: var(--color-blue-700);
--primary-800: var(--color-blue-800);
--primary-900: var(--color-blue-900);
--primary-950: var(--color-blue-950);
--primary: var(--color-primary-600);
--primary-line: transparent;
--primary-foreground: var(--color-white);
--primary-hover: var(--color-primary-700);
--primary-focus: var(--color-primary-700);
--primary-active: var(--color-primary-700);
--primary-checked: var(--color-primary-600);
--secondary: var(--color-gray-900);
--secondary-line: transparent;
--secondary-foreground: var(--color-white);
--secondary-hover: var(--color-gray-800);
--secondary-focus: var(--color-gray-800);
--secondary-active: var(--color-gray-800);
--layer: var(--color-white);
--layer-line: var(--color-gray-200);
--layer-foreground: var(--color-gray-800);
--layer-hover: var(--color-gray-50);
--layer-focus: var(--color-gray-50);
--layer-active: var(--color-gray-50);
--surface: var(--color-gray-100);
--surface-1: var(--color-gray-200);
--surface-2: var(--color-gray-300);
--surface-3: var(--color-gray-400);
--surface-4: var(--color-gray-500);
--surface-5: var(--color-gray-600);
--surface-line: transparent;
--surface-foreground: var(--color-gray-800);
--surface-hover: var(--color-gray-200);
--surface-focus: var(--color-gray-200);
--surface-active: var(--color-gray-200);
--muted: var(--color-gray-50);
--muted-foreground: var(--color-gray-400);
--muted-foreground-1: var(--color-gray-500);
--muted-foreground-2: var(--color-gray-600);
--muted-hover: var(--color-gray-100);
--muted-focus: var(--color-gray-100);
--muted-active: var(--color-gray-100);
--destructive: var(--color-red-500);
--destructive-foreground: var(--color-white);
--destructive-hover: var(--color-red-600);
--destructive-focus: var(--color-red-600);
--navbar: var(--color-white);
--navbar-border: var(--color-gray-200);
--navbar-divider: var(--color-gray-200);
--navbar-nav-foreground: var(--color-gray-800);
--navbar-nav-hover: var(--color-gray-100);
--navbar-nav-focus: var(--color-gray-100);
--navbar-nav-active: var(--color-gray-100);
--navbar-nav-list-divider: var(--color-gray-200);
--navbar-inverse: var(--color-primary-950);
--navbar-1: var(--color-gray-50);
--navbar-1-border: var(--color-gray-200);
--navbar-1-divider: var(--color-gray-200);
--navbar-1-nav-foreground: var(--color-gray-800);
--navbar-1-nav-hover: var(--color-gray-200);
--navbar-1-nav-focus: var(--color-gray-200);
--navbar-1-nav-active: var(--color-gray-200);
--navbar-1-nav-list-divider: var(--color-gray-200);
--navbar-2: var(--color-gray-100);
--navbar-2-border: transparent;
--navbar-2-divider: var(--color-gray-300);
--navbar-2-nav-foreground: var(--color-gray-800);
--navbar-2-nav-hover: var(--color-gray-200);
--navbar-2-nav-focus: var(--color-gray-200);
--navbar-2-nav-active: var(--color-gray-200);
--navbar-2-nav-list-divider: var(--color-gray-200);
--sidebar: var(--color-white);
--sidebar-border: var(--color-gray-200);
--sidebar-divider: var(--color-gray-200);
--sidebar-nav-foreground: var(--color-gray-800);
--sidebar-nav-hover: var(--color-gray-100);
--sidebar-nav-focus: var(--color-gray-100);
--sidebar-nav-active: var(--color-gray-100);
--sidebar-nav-list-divider: var(--color-gray-200);
--sidebar-inverse: var(--color-primary-950);
--sidebar-1: var(--color-gray-50);
--sidebar-1-border: var(--color-gray-200);
--sidebar-1-divider: var(--color-gray-200);
--sidebar-1-nav-foreground: var(--color-gray-800);
--sidebar-1-nav-hover: var(--color-gray-200);
--sidebar-1-nav-focus: var(--color-gray-200);
--sidebar-1-nav-active: var(--color-gray-200);
--sidebar-1-nav-list-divider: var(--color-gray-200);
--sidebar-2: var(--color-gray-100);
--sidebar-2-border: transparent;
--sidebar-2-divider: var(--color-gray-200);
--sidebar-2-nav-foreground: var(--color-gray-800);
--sidebar-2-nav-hover: var(--color-gray-200);
--sidebar-2-nav-focus: var(--color-gray-200);
--sidebar-2-nav-active: var(--color-gray-200);
--sidebar-2-nav-list-divider: var(--color-gray-200);
--card: var(--color-white);
--card-border: var(--color-gray-200);
--card-divider: var(--color-gray-200);
--card-header: var(--color-gray-200);
--card-footer: var(--color-gray-200);
--card-inverse: var(--color-gray-900);
--dropdown: var(--color-white);
--dropdown-1: var(--color-white);
--dropdown-border: transparent;
--dropdown-divider: var(--color-gray-200);
--dropdown-header: var(--color-gray-200);
--dropdown-footer: var(--color-gray-200);
--dropdown-item-foreground: var(--color-gray-800);
--dropdown-item-hover: var(--color-gray-100);
--dropdown-item-focus: var(--color-gray-100);
--dropdown-item-active: var(--color-gray-100);
--dropdown-inverse: var(--color-gray-900);
--select: var(--color-white);
--select-1: var(--color-white);
--select-border: transparent;
--select-item-foreground: var(--color-gray-800);
--select-item-hover: var(--color-gray-100);
--select-item-focus: var(--color-gray-100);
--select-item-active: var(--color-gray-100);
--select-inverse: var(--color-gray-900);
--overlay: var(--color-white);
--overlay-border: transparent;
--overlay-divider: var(--color-gray-200);
--overlay-header: var(--color-gray-200);
--overlay-footer: var(--color-gray-200);
--overlay-inverse: var(--color-gray-900);
--popover: var(--color-white);
--popover-border: var(--color-gray-100);
--tooltip: var(--color-gray-900);
--tooltip-foreground: var(--color-white);
--tooltip-border: transparent;
--table-border: var(--color-gray-200);
--switch: var(--color-white);
--footer: var(--color-white);
--footer-border: var(--color-gray-200);
--footer-inverse: var(--color-gray-900);
--scrollbar-track: var(--color-gray-100);
--scrollbar-thumb: var(--color-gray-300);
--scrollbar-track-inverse: transparent;
--scrollbar-thumb-inverse: var(--color-white);
/* IMPORTANT: Avoid using Tailwind's default color variables for gradient Apexcharts colors.
The Apexcharts plugin does not support the oklch color format, so these colors may not render correctly. */
--chart-colors-background: var(--color-white);
--chart-colors-background-inverse: var(--color-neutral-800);
--chart-colors-foreground: var(--color-gray-800);
--chart-colors-foreground-inverse: var(--color-white);
--chart-primary: var(--color-primary-600);
--chart-colors-primary: var(--color-primary-600);
--chart-colors-primary-inverse: var(--color-primary-500);
--chart-colors-primary-hex: #2563eb; /* var(--color-primary-600); */
--chart-colors-primary-hex-inverse: #3b82f6; /* var(--color-primary-500); */
--chart-colors-chart-inverse: #ffffff; /* var(--color-white); */
--chart-1: var(--color-primary-50);
--chart-colors-chart-1: var(--color-primary-50);
--chart-colors-chart-1-inverse: var(--color-primary-50);
--chart-colors-chart-1-hex: #eff6ff; /* var(--color-primary-50); */
--chart-colors-chart-1-hex-inverse: #eff6ff; /* var(--color-primary-50); */
--chart-2: var(--color-primary-200);
--chart-colors-chart-2: var(--color-primary-200);
--chart-colors-chart-2-inverse: var(--color-primary-200);
--chart-colors-chart-2-hex: #bfdbfe; /* var(--color-primary-200); */
--chart-colors-chart-2-hex-inverse: #bfdbfe; /* var(--color-primary-200); */
--chart-3: var(--color-primary-400);
--chart-colors-chart-3: var(--color-primary-400);
--chart-colors-chart-3-inverse: var(--color-primary-400);
--chart-colors-chart-3-hex: #60a5fa; /* var(--color-primary-400); */
--chart-colors-chart-3-hex-inverse: #60a5fa; /* var(--color-primary-400); */
--chart-4: var(--color-primary-800);
--chart-colors-chart-4: var(--color-primary-800);
--chart-colors-chart-4-inverse: var(--color-primary-800);
--chart-colors-chart-4-hex: #1e40af; /* var(--color-primary-800); */
--chart-colors-chart-4-hex-inverse: #1e40af; /* var(--color-primary-800); */
--chart-5: var(--color-purple-600);
--chart-colors-chart-5: var(--color-purple-600);
--chart-colors-chart-5-inverse: var(--color-purple-500);
--chart-colors-chart-5-hex: #9333ea; /* var(--color-purple-600); */
--chart-colors-chart-5-hex-inverse: #a855f7; /* var(--color-purple-500); */
--chart-6: var(--color-cyan-400);
--chart-colors-chart-6: var(--color-cyan-400);
--chart-colors-chart-6-inverse: var(--color-cyan-400);
--chart-colors-chart-6-hex: #22d3ee; /* var(--color-cyan-400); */
--chart-colors-chart-6-hex-inverse: #22d3ee; /* var(--color-cyan-400); */
--chart-7: var(--color-orange-500);
--chart-colors-chart-7: var(--color-orange-500);
--chart-colors-chart-7-inverse: var(--color-orange-500);
--chart-colors-chart-7-hex: #f97316; /* var(--color-orange-500); */
--chart-colors-chart-7-hex-inverse: #f97316; /* var(--color-orange-500); */
--chart-8: var(--color-gray-100);
--chart-colors-chart-8: var(--color-gray-100);
--chart-colors-chart-8-inverse: var(--color-neutral-700);
--chart-colors-chart-8-hex: #f3f4f6; /* var(--color-gray-100); */
--chart-colors-chart-8-hex-inverse: #404040; /* var(--color-neutral-700); */
--chart-9: var(--color-gray-200);
--chart-colors-chart-9: var(--color-gray-200);
--chart-colors-chart-9-inverse: var(--color-neutral-500);
--chart-colors-chart-9-hex: #e5e7eb; /* var(--color-gray-200); */
--chart-colors-chart-9-hex-inverse: #737373; /* var(--color-neutral-500); */
--chart-10: var(--color-gray-300);
--chart-colors-chart-10: var(--color-gray-300);
--chart-colors-chart-10-inverse: var(--color-neutral-700);
--chart-colors-chart-10-hex: #d1d5db; /* var(--color-gray-300); */
--chart-colors-chart-10-hex-inverse: #404040; /* var(--color-neutral-700); */
--chart-colors-candlestick-upward: var(--color-primary-600);
--chart-colors-candlestick-upward-inverse: var(--color-primary-500);
--chart-colors-candlestick-downward: var(--color-primary-600);
--chart-colors-candlestick-downward-inverse: var(--color-primary-500);
--chart-colors-labels: var(--color-gray-400);
--chart-colors-labels-inverse: var(--color-neutral-400);
--chart-colors-xaxis-labels: var(--color-gray-400);
--chart-colors-xaxis-labels-inverse: var(--color-neutral-400);
--chart-colors-yaxis-labels: var(--color-gray-400);
--chart-colors-yaxis-labels-inverse: var(--color-neutral-400);
--chart-colors-grid-border: var(--color-gray-200);
--chart-colors-grid-border-inverse: var(--color-neutral-700);
--chart-colors-bar-ranges: var(--color-gray-200);
--chart-colors-bar-ranges-inverse: var(--color-white);
--map-colors-primary: var(--color-primary-600);
--map-colors-primary-inverse: var(--color-primary-500);
--map-colors-default: var(--color-gray-300);
--map-colors-default-inverse: var(--color-neutral-600);
--map-colors-highlight: var(--color-primary-300);
--map-colors-highlight-inverse: var(--color-primary-300);
--map-colors-border: var(--color-gray-100);
--map-colors-border-inverse: var(--color-neutral-800);
}
Dark mode
.dark {
--background: var(--color-neutral-800);
--background-1: var(--color-neutral-900);
--background-2: var(--color-neutral-900);
--foreground: var(--color-neutral-200);
--inverse: var(--color-neutral-950);
--border: var(--color-neutral-700);
--border-line-1: var(--color-neutral-800);
--border-line-2: var(--color-neutral-700);
--border-line-3: var(--color-neutral-600);
--border-line-4: var(--color-neutral-500);
--border-line-5: var(--color-neutral-400);
--border-line-6: var(--color-neutral-300);
--border-line-7: var(--color-neutral-200);
--border-line-8: var(--color-neutral-100);
--primary: var(--color-primary-500);
--primary-line: transparent;
--primary-foreground: var(--color-white);
--primary-hover: var(--color-primary-600);
--primary-focus: var(--color-primary-600);
--primary-active: var(--color-primary-600);
--primary-checked: var(--color-primary-500);
--secondary: var(--color-white);
--secondary-line: transparent;
--secondary-foreground: var(--color-neutral-800);
--secondary-hover: var(--color-neutral-100);
--secondary-focus: var(--color-neutral-100);
--secondary-active: var(--color-neutral-100);
--layer: var(--color-neutral-800);
--layer-line: var(--color-neutral-700);
--layer-foreground: var(--color-white);
--layer-hover: var(--color-neutral-700);
--layer-focus: var(--color-neutral-700);
--layer-active: var(--color-neutral-700);
--surface: var(--color-neutral-700);
--surface-1: var(--color-neutral-600);
--surface-2: var(--color-neutral-500);
--surface-3: var(--color-neutral-600);
--surface-4: var(--color-neutral-500);
--surface-5: var(--color-neutral-400);
--surface-line: transparent;
--surface-foreground: var(--color-neutral-200);
--surface-hover: var(--color-neutral-600);
--surface-focus: var(--color-neutral-600);
--surface-active: var(--color-neutral-600);
--muted: var(--color-neutral-800);
--muted-foreground: var(--color-neutral-500);
--muted-foreground-1: var(--color-neutral-400);
--muted-foreground-2: var(--color-neutral-300);
--muted-hover: var(--color-neutral-700);
--muted-focus: var(--color-neutral-700);
--muted-active: var(--color-neutral-700);
--destructive: var(--color-red-500);
--destructive-foreground: var(--color-white);
--destructive-hover: var(--color-red-600);
--destructive-focus: var(--color-red-600);
--navbar: var(--color-neutral-800);
--navbar-border: var(--color-neutral-700);
--navbar-divider: var(--color-neutral-700);
--navbar-nav-foreground: var(--color-neutral-200);
--navbar-nav-hover: var(--color-neutral-700);
--navbar-nav-focus: var(--color-neutral-700);
--navbar-nav-active: var(--color-neutral-700);
--navbar-nav-list-divider: var(--color-neutral-700);
--navbar-inverse: var(--color-primary-950);
--navbar-1: var(--color-neutral-900);
--navbar-1-border: var(--color-neutral-700);
--navbar-1-divider: var(--color-neutral-700);
--navbar-1-nav-foreground: var(--color-neutral-200);
--navbar-1-nav-hover: var(--color-neutral-700);
--navbar-1-nav-focus: var(--color-neutral-700);
--navbar-1-nav-active: var(--color-neutral-700);
--navbar-1-nav-list-divider: var(--color-neutral-700);
--navbar-2: var(--color-neutral-900);
--navbar-2-border: transparent;
--navbar-2-divider: var(--color-neutral-700);
--navbar-2-nav-foreground: var(--color-neutral-200);
--navbar-2-nav-hover: var(--color-neutral-800);
--navbar-2-nav-focus: var(--color-neutral-800);
--navbar-2-nav-active: var(--color-neutral-800);
--navbar-2-nav-list-divider: var(--color-neutral-800);
--sidebar: var(--color-neutral-800);
--sidebar-border: var(--color-neutral-700);
--sidebar-divider: var(--color-neutral-700);
--sidebar-nav-foreground: var(--color-neutral-200);
--sidebar-nav-hover: var(--color-neutral-700);
--sidebar-nav-focus: var(--color-neutral-700);
--sidebar-nav-active: var(--color-neutral-700);
--sidebar-nav-list-divider: var(--color-neutral-700);
--sidebar-inverse: var(--color-primary-950);
--sidebar-1: var(--color-neutral-900);
--sidebar-1-border: var(--color-neutral-700);
--sidebar-1-divider: var(--color-neutral-700);
--sidebar-1-nav-foreground: var(--color-neutral-200);
--sidebar-1-nav-hover: var(--color-neutral-700);
--sidebar-1-nav-focus: var(--color-neutral-700);
--sidebar-1-nav-active: var(--color-neutral-700);
--sidebar-1-nav-list-divider: var(--color-neutral-700);
--sidebar-2: var(--color-neutral-900);
--sidebar-2-border: transparent;
--sidebar-2-divider: var(--color-neutral-800);
--sidebar-2-nav-foreground: var(--color-neutral-200);
--sidebar-2-nav-hover: var(--color-neutral-800);
--sidebar-2-nav-focus: var(--color-neutral-800);
--sidebar-2-nav-active: var(--color-neutral-800);
--sidebar-2-nav-list-divider: var(--color-neutral-800);
--card: var(--color-neutral-800);
--card-border: var(--color-neutral-700);
--card-divider: var(--color-neutral-700);
--card-header: var(--color-neutral-700);
--card-footer: var(--color-neutral-700);
--card-inverse: var(--color-neutral-900);
--dropdown: var(--color-neutral-900);
--dropdown-1: var(--color-neutral-950);
--dropdown-border: transparent;
--dropdown-divider: var(--color-neutral-800);
--dropdown-header: var(--color-neutral-700);
--dropdown-footer: var(--color-neutral-700);
--dropdown-item-foreground: var(--color-neutral-200);
--dropdown-item-hover: var(--color-neutral-800);
--dropdown-item-focus: var(--color-neutral-800);
--dropdown-item-active: var(--color-neutral-800);
--dropdown-inverse: var(--color-neutral-900);
--select: var(--color-neutral-900);
--select-1: var(--color-neutral-950);
--select-border: transparent;
--select-item-foreground: var(--color-neutral-200);
--select-item-hover: var(--color-neutral-800);
--select-item-focus: var(--color-neutral-800);
--select-item-active: var(--color-neutral-800);
--select-inverse: var(--color-neutral-900);
--overlay: var(--color-neutral-800);
--overlay-border: transparent;
--overlay-divider: var(--color-neutral-700);
--overlay-header: var(--color-neutral-700);
--overlay-footer: var(--color-neutral-700);
--overlay-inverse: var(--color-neutral-900);
--popover: var(--color-neutral-900);
--popover-border: var(--color-neutral-700);
--tooltip: var(--color-white);
--tooltip-foreground: var(--color-neutral-800);
--tooltip-border: transparent;
--table-border: var(--color-neutral-700);
--footer: var(--color-neutral-800);
--footer-border: var(--color-neutral-700);
--footer-inverse: var(--color-neutral-900);
--scrollbar-track: var(--color-neutral-700);
--scrollbar-thumb: var(--color-neutral-500);
--scrollbar-track-inverse: var(--color-neutral-500);
--scrollbar-thumb-inverse: var(--color-neutral-700);
--chart-primary: var(--color-primary-500);
--chart-8: var(--color-neutral-700);
--chart-9: var(--color-neutral-500);
--chart-10: var(--color-neutral-700);
}
Theme files have three main sections. Understanding when to edit each section is key to successful customization.
To avoid conflicts when updating Preline, don't modify the shipped theme.css directly. Instead, duplicate it (for example my-theme.css) and import your copy after the base theme. You can also use (or copy) another premade theme (for example harvest.css) as a starting point.
@import "tailwindcss";
/* Base theme tokens + mappings */
@import "./themes/theme.css";
/* Your theme overrides (copied from theme.css or another premade theme) */
@import "./themes/my-theme.css";
@theme inline { }
The default mappings live in the base theme.css. You generally don't need to copy them.
Only add/override mappings in my-theme.css when:
/* Only add/override mappings here when you introduce new tokens or want to change a mapping */
@theme inline {
/* Adding a new custom token */
--color-my-brand: var(--my-brand);
/* (optional) if you ever need to change a mapping */
/* --color-primary: var(--my-new-primary); */
}
:root { }
Define the actual values for light mode in your copied theme file (for example my-theme.css). Assign values using Tailwind color variables or custom hex/rgb/oklch values.
:root {
/* Using Tailwind color variables */
--primary: var(--color-blue-600);
--primary-hover: var(--color-blue-700);
--primary-foreground: var(--color-white);
/* Or using custom values */
--primary: #2563eb;
--primary-hover: #1d4ed8;
/* Or using oklch values */
--background: oklch(100% 0 0);
--foreground: oklch(32.11% 0.02 264.05);
--border: oklch(92.76% 0.01 264.53);
/* Custom token from @theme inline */
--my-brand: var(--color-purple-600);
}
.dark { }
Override token values for dark mode in your copied theme file. Only include tokens that need different values, unspecified tokens inherit from :root. Dark mode is controlled separately via the .dark class. Learn more about the Dark Mode in the dedicated documentation page here.
.dark {
--primary: var(--color-blue-500);
--primary-hover: var(--color-blue-400);
--background: var(--color-neutral-800);
--foreground: var(--color-neutral-200);
--border: var(--color-neutral-700);
/* Custom token from @theme inline */
--my-brand: var(--color-purple-400);
}
Preline Themes focus on colors, but typography can be themed via Tailwind font tokens (for example --font-sans).
Fonts must be imported at the top of CSS file. Alternatively, they can be linked in HTML files.
@import url('https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap');
/* tailwind.css */
@import "tailwindcss";
/* Base theme tokens + mappings */
@import "./themes/theme.css";
/* Your theme overrides (copied from theme.css or another premade theme) */
@import "./themes/my-theme.css";
Now, you can reference the font with the --font-sans token in your my-theme.css file by adding the following code to :root section:
:root {
/* Using Google Fonts */
--font-sans: "Inter", ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, Noto Sans, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;
/* Using Tailwind color variables */
--primary: var(--color-blue-600);
--primary-hover: var(--color-blue-700);
--primary-foreground: var(--color-white);
/* Or using custom values */
--primary: #2563eb;
--primary-hover: #1d4ed8;
/* Or using oklch values */
--background: oklch(100% 0 0);
--foreground: oklch(32.11% 0.02 264.05);
--border: oklch(92.76% 0.01 264.53);
/* Custom token from @theme inline */
--my-brand: var(--color-purple-600);
}
The above example refers to Sans Serif --font-sans token. If you are using Serif --font-serif or Mono --font-mono, you may need to adjust the token name accordingly.
To use Agent Skills, you will need to set them up in your agentic IDE or CLI first. The setup is simple and takes only a moment.
Preline comes with Agent Skills that can generate a custom theme for you. You may generate a new theme in any Agentic Coding Tools (e.g. IDE, CLI) like Cursor, Claude Code, Google Antigravity or VS Code. In your IDE or CLI simply ask the agent to generate a new theme for you in plain English.
For example, you can ask the agent to generate a theme for you like this:
Generate a soft rose theme using SKILL
You can be as descriptive as you like (mood, brand, contrast, typography), the agent will infer the rest.
By default, the Preline Agent SKILL generates a theme for light mode and applies a matching neutral palette for dark mode. However, you can ask the agent to generate a theme for dark mode as well by adding the following prompt:
Generate a soft rose theme with a matching dark mode using SKILL
The agent will generate a theme for you and save it to the themes folder in your project. You can then import the theme into your main.css. Read more on Customize tokens section to learn how to import the theme into your project.
Fun fact: The Olive theme was generated using this method and used in the Preline.