Design Systems 9 min read

shadcn/ui Theme Customization: The Complete Guide

How to customize shadcn/ui themes with CSS variables — colors, radius, fonts — and how to use LiveTheme to design and export shadcn themes visually.

How shadcn/ui theming works

shadcn/ui components are built on CSS custom properties (CSS variables) defined in your globals.css. Unlike typical component libraries, shadcn/ui is not a package you install — you copy component source code into your project and style it through CSS variables.

The default variable set uses HSL format for all colors:

/* globals.css */
:root {
  --background: 0 0% 100%;
  --foreground: 222.2 84% 4.9%;
  --primary: 262.1 83.3% 57.8%;
  --primary-foreground: 210 40% 98%;
  --secondary: 210 40% 96.1%;
  --secondary-foreground: 222.2 47.4% 11.2%;
  --muted: 210 40% 96.1%;
  --muted-foreground: 215.4 16.3% 46.9%;
  --accent: 210 40% 96.1%;
  --accent-foreground: 222.2 47.4% 11.2%;
  --destructive: 0 84.2% 60.2%;
  --destructive-foreground: 210 40% 98%;
  --border: 214.3 31.8% 91.4%;
  --input: 214.3 31.8% 91.4%;
  --ring: 262.1 83.3% 57.8%;
  --radius: 0.5rem;
}

The shadcn token system

  • background / foreground: page background and default text
  • card / card-foreground: card component surface
  • popover / popover-foreground: dropdown and tooltip surface
  • primary / primary-foreground: main action color
  • secondary / secondary-foreground: secondary actions
  • muted / muted-foreground: placeholder text, subtle UI
  • accent / accent-foreground: highlight states
  • destructive / destructive-foreground: error/delete actions
  • border: component borders
  • input: input field borders
  • ring: focus rings
  • radius: global border radius

Dark mode in shadcn/ui

shadcn/ui uses a .dark class on the <html> element to switch themes:

.dark {
  --background: 222.2 84% 4.9%;
  --foreground: 210 40% 98%;
  --primary: 263.4 70% 50.4%;
  --primary-foreground: 210 40% 98%;
  /* ... */
}

Customizing shadcn/ui colors step by step

1. Choose your brand primary

Convert your brand hex to HSL. The easiest way: open browser devtools, set background: #yourhex on any element, then inspect the computed HSL value. Or use a converter tool.

2. Derive foreground colors for contrast

For each color token you set, choose a foreground that achieves at minimum 4.5:1 contrast ratio (WCAG AA for normal text). Typically white works on saturated darks and black works on light/pastel colors.

3. Update muted and accent

Muted should be a very low-saturation version of your primary hue. Accent typically matches your secondary or is a slightly tinted version of the background.

4. Check ring and border

Ring should match your primary (visible focus indicator). Border should be a subtly visible neutral against your card/background.

Using LiveTheme to generate shadcn/ui themes

LiveTheme's editor supports shadcn/ui as a first-class export target. The workflow:

  1. Open the editor and choose or customize your colors
  2. Switch to a shadcn/ui preview template (Shadcn Login, Dashboard 01, or Shadcn Mock)
  3. See your colors applied to real shadcn components in real-time
  4. Click Export → shadcn/ui to get the ready-to-paste CSS for both light and dark modes

shadcn/ui with Tailwind v4

shadcn/ui is migrating to use OKLCH-based CSS variables in the Tailwind v4 format. The new variable format will look like:

:root {
  --primary: oklch(0.53 0.28 291);
  --primary-foreground: oklch(0.97 0.02 291);
}

LiveTheme generates OKLCH-native export code, ready for this migration.

Common shadcn/ui theming mistakes

  • Forgetting dark mode variants — always define .dark { } overrides.
  • Ignoring ring — a poorly chosen ring color makes keyboard navigation invisible.
  • Setting muted the same as background — muted should be slightly more prominent than the background.
  • Not updating Card foreground — card-foreground often defaults to the same as foreground, but on colored card surfaces it needs adjustment.
#shadcn/ui#theming#CSS variables#React#Next.js#design system