Tailwind CSS

Tailwind v4 + DaisyUI setup, oklch design tokens, and the GOaT design system.

The GOaT stack uses Tailwind CSS v4 with DaisyUI for component classes and oklch color tokens for a modern, dark-first design system.

Setup

styles/main.css:

@import "tailwindcss";
@plugin "daisyui";

Build with the Tailwind CLI:

npx @tailwindcss/cli -i styles/main.css -o static/styles.css --watch

Or for dev, use the CDN (no build step):

<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<link href="https://cdn.jsdelivr.net/npm/daisyui@5/full.css" rel="stylesheet">

Dark-First Theme

Define your theme using DaisyUI’s @plugin syntax with oklch colors:

@plugin "daisyui/theme" {
  name: "myapp-dark";
  default: true;
  prefersdark: true;
  color-scheme: dark;

  --color-base-100: oklch(14% 0.01 260);
  --color-base-200: oklch(18% 0.012 260);
  --color-base-300: oklch(23% 0.015 260);
  --color-base-content: oklch(93% 0.008 260);

  --color-primary: oklch(74% 0.19 45);       /* Electric orange */
  --color-primary-content: oklch(14% 0.01 45);

  --color-accent: oklch(82% 0.14 85);        /* Warm amber/gold */
  --color-accent-content: oklch(20% 0.04 85);

  --color-success: oklch(72% 0.17 155);
  --color-error: oklch(65% 0.2 25);

  --radius-box: 0.5rem;
  --border: 1px;
  --depth: 1;
}

Why oklch?

oklch is perceptually uniform — colors at the same lightness look the same lightness. This makes your design system predictable:

/* These all feel equally "vibrant" */
--color-primary: oklch(74% 0.19 45);    /* Orange */
--color-success: oklch(72% 0.17 155);   /* Green */
--color-error:   oklch(65% 0.2 25);     /* Red */
--color-info:    oklch(70% 0.14 250);   /* Blue */

Custom Components

Build reusable component classes that complement DaisyUI:

/* Frosted glass card */
.card-glass {
  background: oklch(from var(--color-base-200) l c h / 0.6);
  backdrop-filter: blur(12px) saturate(1.4);
  border: 1px solid oklch(from var(--color-base-content) l c h / 0.08);
}

/* Gradient CTA button */
.btn-gradient {
  background: linear-gradient(135deg, oklch(74% 0.19 45), oklch(78% 0.17 60));
  color: oklch(14% 0.01 45);
  border: none;
}
.btn-gradient:hover {
  transform: translateY(-1px);
  box-shadow: 0 4px 16px oklch(from var(--color-primary) l c h / 0.3);
}

/* Frosted glass nav */
.nav-glass {
  background: oklch(from var(--color-base-100) l c h / 0.8);
  backdrop-filter: blur(16px) saturate(1.5);
  border-bottom: 1px solid oklch(from var(--color-base-content) l c h / 0.06);
}

Typography

Pair display and body fonts for visual hierarchy:

html {
  font-family: 'Inter', system-ui, sans-serif;
}

h1, h2, h3, .font-display {
  font-family: 'Clash Display', 'Inter', system-ui, sans-serif;
  font-weight: 600;
  letter-spacing: -0.02em;
}

.font-mono, code, pre {
  font-family: 'JetBrains Mono', monospace;
}

/* Uppercase labels for sporting/data-dense UIs */
.label-uppercase {
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 600;
  font-size: 0.75rem;
}

Motion Tokens

Respect user preferences and keep animations consistent:

:root {
  --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-out-back: cubic-bezier(0.34, 1.56, 0.64, 1);
  --duration-fast: 120ms;
  --duration-base: 200ms;
}

@media (prefers-reduced-motion: reduce) {
  :root {
    --duration-fast: 0ms;
    --duration-base: 0ms;
  }
}

Gotchas

  • Use the Tailwind CLI for production. CDN mode is fine for dev but doesn’t tree-shake.
  • DaisyUI v5 uses @plugin syntax. Not the old daisyui: { themes: [] } config.
  • oklch from syntax (oklch(from var(--color-base-200) l c h / 0.6)) requires modern browsers. All evergreen browsers support it.
  • Don’t fight DaisyUI. Use its component classes (btn, card, badge) and extend, don’t rebuild from scratch.