We use cookies to enhance your experience on the site
CodeWorlds
Back to collections
Guide41 min read

DaisyUI - Kompletny Przewodnik po Bibliotece Komponentów dla Tailwind CSS

DaisyUI is the most popular Tailwind CSS plugin offering ready-made UI components with semantic classes. Discover its full capabilities, themes, components, and integration with React, Vue, Svelte.

DaisyUI - Kompletny Przewodnik po Komponentach dla Tailwind CSS

Czym jest DaisyUI?

DaisyUI to najpopularniejszy plugin do Tailwind CSS, który dodaje gotowe klasy komponentów do Twojego projektu. Zamiast pisać dziesiątki klas utility jak bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-4 rounded, piszesz po prostu btn btn-primary. To najlepsza rzecz, jaka mogła się przydarzyć Tailwind CSS.

DaisyUI nie zastępuje Tailwind - rozszerza go. Nadal możesz używać wszystkich klas utility Tailwind razem z semantycznymi klasami DaisyUI. Dzięki temu masz elastyczność Tailwind z wygodą gotowych komponentów, a wszystko to bez żadnego JavaScript - DaisyUI to czysty CSS.

Dlaczego DaisyUI?

Kluczowe zalety DaisyUI

  1. Semantyczne klasy - btn zamiast bg-blue-500 hover:bg-blue-600...
  2. 35+ tematów - Łatwa zmiana wyglądu całej aplikacji
  3. Zero JavaScript - Czysty CSS, działa z każdym frameworkiem
  4. Pełna kompatybilność - Działa z React, Vue, Svelte, Angular, vanilla HTML
  5. Mniejszy bundle - Mniej klas = mniejszy CSS
  6. 100% darmowy - MIT License, open source

DaisyUI vs inne rozwiązania

CechaDaisyUITailwind UIHeadless UIBootstrap
CenaDarmowy$299+DarmowyDarmowy
JavaScriptNie wymagaTakTakTak
TailwindNatywnyNatywnyNatywnyOsobny
Komponenty50+500+1025+
Tematy35+BrakBrakOgraniczone
CustomizacjaPełnaPełnaPełnaOgraniczona
Bundle sizeMinimalnyŚredniMinimalnyDuży

Instalacja i konfiguracja

Instalacja npm

Code
Bash
# npm
npm install -D daisyui@latest

# pnpm
pnpm add -D daisyui@latest

# yarn
yarn add -D daisyui@latest

# bun
bun add -D daisyui@latest

Konfiguracja Tailwind CSS v3

JStailwind.config.js
JavaScript
// tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    "./src/**/*.{js,ts,jsx,tsx,html}",
    "./components/**/*.{js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [
    require("daisyui"),
  ],
  daisyui: {
    themes: ["light", "dark", "cupcake", "cyberpunk", "valentine", "forest"],
    darkTheme: "dark",
    base: true,
    styled: true,
    utils: true,
    prefix: "",
    logs: true,
    themeRoot: ":root",
  },
}

Konfiguracja Tailwind CSS v4

JStailwind.config.js
JavaScript
// tailwind.config.js (v4)
import daisyui from "daisyui"

export default {
  plugins: [daisyui],
  daisyui: {
    themes: ["light", "dark"],
  },
}

Weryfikacja instalacji

Code
HTML
<!-- Sprawdź czy DaisyUI działa -->
<button class="btn btn-primary">
  Jeśli ten przycisk jest stylizowany, DaisyUI działa!
</button>

Komponenty DaisyUI

Przyciski (Button)

Code
HTML
<!-- Podstawowe warianty -->
<button class="btn">Default</button>
<button class="btn btn-neutral">Neutral</button>
<button class="btn btn-primary">Primary</button>
<button class="btn btn-secondary">Secondary</button>
<button class="btn btn-accent">Accent</button>
<button class="btn btn-ghost">Ghost</button>
<button class="btn btn-link">Link</button>

<!-- Stany -->
<button class="btn btn-info">Info</button>
<button class="btn btn-success">Success</button>
<button class="btn btn-warning">Warning</button>
<button class="btn btn-error">Error</button>

<!-- Rozmiary -->
<button class="btn btn-lg">Large</button>
<button class="btn btn-md">Medium (default)</button>
<button class="btn btn-sm">Small</button>
<button class="btn btn-xs">Extra small</button>

<!-- Modyfikatory -->
<button class="btn btn-wide">Wide</button>
<button class="btn btn-block">Block (full width)</button>
<button class="btn btn-circle"></button>
<button class="btn btn-square"></button>

<!-- Stany interaktywne -->
<button class="btn btn-outline btn-primary">Outline</button>
<button class="btn btn-active">Active</button>
<button class="btn btn-disabled">Disabled</button>
<button class="btn loading">Loading...</button>

<!-- Z ikoną -->
<button class="btn btn-primary gap-2">
  <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
    <path d="M10 12a2 2 0 100-4 2 2 0 000 4z" />
  </svg>
  Settings
</button>

Karty (Card)

Code
HTML
<!-- Podstawowa karta -->
<div class="card w-96 bg-base-100 shadow-xl">
  <figure>
    <img src="https://picsum.photos/400/200" alt="Image" />
  </figure>
  <div class="card-body">
    <h2 class="card-title">Tytuł karty</h2>
    <p>Opis karty z dodatkowym tekstem wyjaśniającym zawartość.</p>
    <div class="card-actions justify-end">
      <button class="btn btn-primary">Kup teraz</button>
    </div>
  </div>
</div>

<!-- Karta kompaktowa -->
<div class="card card-compact w-96 bg-base-100 shadow-xl">
  <figure><img src="image.jpg" alt="Photo" /></figure>
  <div class="card-body">
    <h2 class="card-title">Kompaktowa!</h2>
    <p>Mniej paddingu</p>
    <div class="card-actions justify-end">
      <button class="btn btn-primary btn-sm">Akcja</button>
    </div>
  </div>
</div>

<!-- Karta z badge -->
<div class="card w-96 bg-base-100 shadow-xl">
  <div class="card-body">
    <h2 class="card-title">
      Produkt
      <div class="badge badge-secondary">NEW</div>
    </h2>
    <p>Opis produktu</p>
    <div class="card-actions justify-end">
      <div class="badge badge-outline">Fashion</div>
      <div class="badge badge-outline">Products</div>
    </div>
  </div>
</div>

<!-- Karta pozioma -->
<div class="card card-side bg-base-100 shadow-xl">
  <figure><img src="image.jpg" alt="Movie" class="w-48" /></figure>
  <div class="card-body">
    <h2 class="card-title">Film</h2>
    <p>Opis filmu</p>
    <div class="card-actions justify-end">
      <button class="btn btn-primary">Oglądaj</button>
    </div>
  </div>
</div>

<!-- Karta z overlay -->
<div class="card w-96 bg-base-100 shadow-xl image-full">
  <figure><img src="background.jpg" alt="Background" /></figure>
  <div class="card-body">
    <h2 class="card-title">Tytuł</h2>
    <p>Tekst na tle obrazu</p>
    <div class="card-actions justify-end">
      <button class="btn btn-primary">Akcja</button>
    </div>
  </div>
</div>

Modal

Code
HTML
<!-- Modal z przyciskiem -->
<button class="btn" onclick="my_modal_1.showModal()">Otwórz Modal</button>

<dialog id="my_modal_1" class="modal">
  <div class="modal-box">
    <h3 class="font-bold text-lg">Witaj!</h3>
    <p class="py-4">Naciśnij ESC lub kliknij przycisk, aby zamknąć</p>
    <div class="modal-action">
      <form method="dialog">
        <button class="btn">Zamknij</button>
      </form>
    </div>
  </div>
</dialog>

<!-- Modal z backdrop do zamknięcia -->
<button class="btn" onclick="my_modal_2.showModal()">Modal z backdrop</button>

<dialog id="my_modal_2" class="modal">
  <div class="modal-box">
    <h3 class="font-bold text-lg">Modal</h3>
    <p class="py-4">Kliknij poza modal aby zamknąć</p>
  </div>
  <form method="dialog" class="modal-backdrop">
    <button>close</button>
  </form>
</dialog>

<!-- Modal z akcjami -->
<dialog id="my_modal_3" class="modal">
  <div class="modal-box">
    <form method="dialog">
      <button class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2"></button>
    </form>
    <h3 class="font-bold text-lg">Potwierdź akcję</h3>
    <p class="py-4">Czy na pewno chcesz kontynuować?</p>
    <div class="modal-action">
      <form method="dialog">
        <button class="btn btn-ghost">Anuluj</button>
        <button class="btn btn-primary">Potwierdź</button>
      </form>
    </div>
  </div>
</dialog>

Nawigacja (Navbar)

Code
HTML
<!-- Prosty navbar -->
<div class="navbar bg-base-100">
  <a class="btn btn-ghost text-xl">daisyUI</a>
</div>

<!-- Navbar z menu -->
<div class="navbar bg-base-100">
  <div class="flex-1">
    <a class="btn btn-ghost text-xl">Logo</a>
  </div>
  <div class="flex-none">
    <ul class="menu menu-horizontal px-1">
      <li><a>Link 1</a></li>
      <li><a>Link 2</a></li>
    </ul>
  </div>
</div>

<!-- Navbar z wyszukiwaniem i awatarem -->
<div class="navbar bg-base-100">
  <div class="flex-1">
    <a class="btn btn-ghost text-xl">Logo</a>
  </div>
  <div class="flex-none gap-2">
    <div class="form-control">
      <input type="text" placeholder="Szukaj" class="input input-bordered w-24 md:w-auto" />
    </div>
    <div class="dropdown dropdown-end">
      <div tabindex="0" role="button" class="btn btn-ghost btn-circle avatar">
        <div class="w-10 rounded-full">
          <img alt="Avatar" src="avatar.jpg" />
        </div>
      </div>
      <ul tabindex="0" class="mt-3 z-[1] p-2 shadow menu menu-sm dropdown-content bg-base-100 rounded-box w-52">
        <li><a>Profil</a></li>
        <li><a>Ustawienia</a></li>
        <li><a>Wyloguj</a></li>
      </ul>
    </div>
  </div>
</div>

<!-- Navbar z ikonami -->
<div class="navbar bg-neutral text-neutral-content">
  <div class="flex-1">
    <a class="btn btn-ghost text-xl">daisyUI</a>
  </div>
  <div class="flex-none">
    <button class="btn btn-square btn-ghost">
      <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="inline-block w-5 h-5 stroke-current">
        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 12h.01M12 12h.01M19 12h.01M6 12a1 1 0 11-2 0 1 1 0 012 0zm7 0a1 1 0 11-2 0 1 1 0 012 0zm7 0a1 1 0 11-2 0 1 1 0 012 0z"></path>
      </svg>
    </button>
  </div>
</div>

Formularze

Code
HTML
<!-- Input -->
<div class="form-control w-full max-w-xs">
  <label class="label">
    <span class="label-text">Email</span>
    <span class="label-text-alt">Wymagane</span>
  </label>
  <input type="email" placeholder="email@example.com" class="input input-bordered w-full max-w-xs" />
  <label class="label">
    <span class="label-text-alt">Wprowadź poprawny email</span>
  </label>
</div>

<!-- Input z wariantami -->
<input type="text" placeholder="Default" class="input input-bordered w-full max-w-xs" />
<input type="text" placeholder="Primary" class="input input-bordered input-primary w-full max-w-xs" />
<input type="text" placeholder="Secondary" class="input input-bordered input-secondary w-full max-w-xs" />
<input type="text" placeholder="Accent" class="input input-bordered input-accent w-full max-w-xs" />
<input type="text" placeholder="Info" class="input input-bordered input-info w-full max-w-xs" />
<input type="text" placeholder="Success" class="input input-bordered input-success w-full max-w-xs" />
<input type="text" placeholder="Warning" class="input input-bordered input-warning w-full max-w-xs" />
<input type="text" placeholder="Error" class="input input-bordered input-error w-full max-w-xs" />

<!-- Rozmiary -->
<input type="text" placeholder="Large" class="input input-bordered input-lg" />
<input type="text" placeholder="Medium" class="input input-bordered input-md" />
<input type="text" placeholder="Small" class="input input-bordered input-sm" />
<input type="text" placeholder="XS" class="input input-bordered input-xs" />

<!-- Select -->
<select class="select select-bordered w-full max-w-xs">
  <option disabled selected>Wybierz opcję</option>
  <option>Opcja 1</option>
  <option>Opcja 2</option>
  <option>Opcja 3</option>
</select>

<!-- Textarea -->
<textarea class="textarea textarea-bordered" placeholder="Twoja wiadomość"></textarea>

<!-- Checkbox -->
<div class="form-control">
  <label class="label cursor-pointer">
    <span class="label-text">Zapamiętaj mnie</span>
    <input type="checkbox" checked class="checkbox checkbox-primary" />
  </label>
</div>

<!-- Radio -->
<div class="form-control">
  <label class="label cursor-pointer">
    <span class="label-text">Opcja A</span>
    <input type="radio" name="radio-1" class="radio radio-primary" checked />
  </label>
  <label class="label cursor-pointer">
    <span class="label-text">Opcja B</span>
    <input type="radio" name="radio-1" class="radio radio-primary" />
  </label>
</div>

<!-- Toggle -->
<input type="checkbox" class="toggle toggle-primary" checked />

<!-- Range -->
<input type="range" min="0" max="100" value="40" class="range range-primary" />

<!-- Rating -->
<div class="rating">
  <input type="radio" name="rating-1" class="mask mask-star" />
  <input type="radio" name="rating-1" class="mask mask-star" checked />
  <input type="radio" name="rating-1" class="mask mask-star" />
  <input type="radio" name="rating-1" class="mask mask-star" />
  <input type="radio" name="rating-1" class="mask mask-star" />
</div>

<!-- File input -->
<input type="file" class="file-input file-input-bordered w-full max-w-xs" />

Tabele

Code
HTML
<!-- Podstawowa tabela -->
<div class="overflow-x-auto">
  <table class="table">
    <thead>
      <tr>
        <th></th>
        <th>Imię</th>
        <th>Stanowisko</th>
        <th>Email</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <th>1</th>
        <td>Jan Kowalski</td>
        <td>Developer</td>
        <td>jan@example.com</td>
      </tr>
      <tr>
        <th>2</th>
        <td>Anna Nowak</td>
        <td>Designer</td>
        <td>anna@example.com</td>
      </tr>
      <tr>
        <th>3</th>
        <td>Piotr Wiśniewski</td>
        <td>Manager</td>
        <td>piotr@example.com</td>
      </tr>
    </tbody>
  </table>
</div>

<!-- Tabela zebra -->
<table class="table table-zebra">
  <!-- ... -->
</table>

<!-- Tabela z hover -->
<table class="table">
  <tbody>
    <tr class="hover">
      <td>Row with hover effect</td>
    </tr>
  </tbody>
</table>

<!-- Tabela aktywna -->
<table class="table">
  <tbody>
    <tr class="active">
      <td>Active row (highlighted)</td>
    </tr>
  </tbody>
</table>

<!-- Kompaktowa tabela -->
<table class="table table-xs">
  <!-- Mniejszy padding -->
</table>

Alerty i powiadomienia

Code
HTML
<!-- Alert podstawowy -->
<div class="alert">
  <span>12 nieprzeczytanych wiadomości.</span>
</div>

<!-- Alert info -->
<div class="alert alert-info">
  <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="stroke-current shrink-0 w-6 h-6">
    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
  </svg>
  <span>Nowa aktualizacja oprogramowania jest dostępna.</span>
</div>

<!-- Alert success -->
<div class="alert alert-success">
  <svg xmlns="http://www.w3.org/2000/svg" class="stroke-current shrink-0 h-6 w-6" fill="none" viewBox="0 0 24 24">
    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
  </svg>
  <span>Twoje zamówienie zostało potwierdzone!</span>
</div>

<!-- Alert warning -->
<div class="alert alert-warning">
  <svg xmlns="http://www.w3.org/2000/svg" class="stroke-current shrink-0 h-6 w-6" fill="none" viewBox="0 0 24 24">
    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
  </svg>
  <span>Uwaga: Twoja sesja wygasa za 5 minut!</span>
</div>

<!-- Alert error -->
<div class="alert alert-error">
  <svg xmlns="http://www.w3.org/2000/svg" class="stroke-current shrink-0 h-6 w-6" fill="none" viewBox="0 0 24 24">
    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z" />
  </svg>
  <span>Błąd! Coś poszło nie tak.</span>
</div>

<!-- Alert z akcjami -->
<div class="alert">
  <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="stroke-info shrink-0 w-6 h-6">
    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
  </svg>
  <span>Mamy nowe warunki użytkowania.</span>
  <div>
    <button class="btn btn-sm">Odmów</button>
    <button class="btn btn-sm btn-primary">Akceptuj</button>
  </div>
</div>

<!-- Toast -->
<div class="toast toast-end">
  <div class="alert alert-info">
    <span>Nowa wiadomość.</span>
  </div>
</div>

Badge i Indicator

Code
HTML
<!-- Badge -->
<span class="badge">default</span>
<span class="badge badge-neutral">neutral</span>
<span class="badge badge-primary">primary</span>
<span class="badge badge-secondary">secondary</span>
<span class="badge badge-accent">accent</span>
<span class="badge badge-ghost">ghost</span>

<!-- Badge outline -->
<span class="badge badge-outline">outline</span>
<span class="badge badge-outline badge-primary">primary</span>

<!-- Badge rozmiary -->
<span class="badge badge-lg">Large</span>
<span class="badge badge-md">Medium</span>
<span class="badge badge-sm">Small</span>
<span class="badge badge-xs">Tiny</span>

<!-- Badge w przycisku -->
<button class="btn gap-2">
  Inbox
  <span class="badge badge-sm">+99</span>
</button>

<!-- Indicator -->
<div class="indicator">
  <span class="indicator-item badge badge-primary">new</span>
  <div class="grid w-32 h-32 bg-base-300 place-items-center">content</div>
</div>

<!-- Indicator na awatarze -->
<div class="indicator">
  <span class="indicator-item badge badge-secondary">online</span>
  <div class="avatar">
    <div class="w-12 rounded">
      <img src="avatar.jpg" alt="Avatar" />
    </div>
  </div>
</div>

Collapse i Accordion

Code
HTML
<!-- Collapse -->
<div class="collapse bg-base-200">
  <input type="checkbox" />
  <div class="collapse-title text-xl font-medium">
    Kliknij, aby rozwinąć
  </div>
  <div class="collapse-content">
    <p>Ukryta treść pojawia się po kliknięciu.</p>
  </div>
</div>

<!-- Collapse z arrow -->
<div class="collapse collapse-arrow bg-base-200">
  <input type="checkbox" />
  <div class="collapse-title text-xl font-medium">
    Kliknij, aby rozwinąć
  </div>
  <div class="collapse-content">
    <p>Treść z ikoną strzałki.</p>
  </div>
</div>

<!-- Collapse z plus -->
<div class="collapse collapse-plus bg-base-200">
  <input type="checkbox" />
  <div class="collapse-title text-xl font-medium">
    Kliknij, aby rozwinąć
  </div>
  <div class="collapse-content">
    <p>Treść z ikoną plus/minus.</p>
  </div>
</div>

<!-- Accordion (radio - tylko jeden otwarty) -->
<div class="join join-vertical w-full">
  <div class="collapse collapse-arrow join-item border border-base-300">
    <input type="radio" name="my-accordion-1" checked />
    <div class="collapse-title text-xl font-medium">
      Pytanie 1
    </div>
    <div class="collapse-content">
      <p>Odpowiedź na pytanie 1.</p>
    </div>
  </div>
  <div class="collapse collapse-arrow join-item border border-base-300">
    <input type="radio" name="my-accordion-1" />
    <div class="collapse-title text-xl font-medium">
      Pytanie 2
    </div>
    <div class="collapse-content">
      <p>Odpowiedź na pytanie 2.</p>
    </div>
  </div>
  <div class="collapse collapse-arrow join-item border border-base-300">
    <input type="radio" name="my-accordion-1" />
    <div class="collapse-title text-xl font-medium">
      Pytanie 3
    </div>
    <div class="collapse-content">
      <p>Odpowiedź na pytanie 3.</p>
    </div>
  </div>
</div>

Tabs

Code
HTML
<!-- Podstawowe tabs -->
<div role="tablist" class="tabs tabs-bordered">
  <a role="tab" class="tab">Tab 1</a>
  <a role="tab" class="tab tab-active">Tab 2</a>
  <a role="tab" class="tab">Tab 3</a>
</div>

<!-- Tabs lifted -->
<div role="tablist" class="tabs tabs-lifted">
  <a role="tab" class="tab">Tab 1</a>
  <a role="tab" class="tab tab-active">Tab 2</a>
  <a role="tab" class="tab">Tab 3</a>
</div>

<!-- Tabs boxed -->
<div role="tablist" class="tabs tabs-boxed">
  <a role="tab" class="tab">Tab 1</a>
  <a role="tab" class="tab tab-active">Tab 2</a>
  <a role="tab" class="tab">Tab 3</a>
</div>

<!-- Tabs z zawartością (radio) -->
<div role="tablist" class="tabs tabs-lifted">
  <input type="radio" name="my_tabs_1" role="tab" class="tab" aria-label="Tab 1" />
  <div role="tabpanel" class="tab-content bg-base-100 border-base-300 rounded-box p-6">
    Zawartość Tab 1
  </div>

  <input type="radio" name="my_tabs_1" role="tab" class="tab" aria-label="Tab 2" checked />
  <div role="tabpanel" class="tab-content bg-base-100 border-base-300 rounded-box p-6">
    Zawartość Tab 2
  </div>

  <input type="radio" name="my_tabs_1" role="tab" class="tab" aria-label="Tab 3" />
  <div role="tabpanel" class="tab-content bg-base-100 border-base-300 rounded-box p-6">
    Zawartość Tab 3
  </div>
</div>

Progress i Loading

Code
HTML
<!-- Progress bar -->
<progress class="progress w-56" value="0" max="100"></progress>
<progress class="progress w-56" value="25" max="100"></progress>
<progress class="progress w-56" value="50" max="100"></progress>
<progress class="progress w-56" value="75" max="100"></progress>
<progress class="progress w-56" value="100" max="100"></progress>

<!-- Progress z kolorami -->
<progress class="progress progress-primary w-56" value="40" max="100"></progress>
<progress class="progress progress-secondary w-56" value="60" max="100"></progress>
<progress class="progress progress-accent w-56" value="80" max="100"></progress>
<progress class="progress progress-info w-56" value="45" max="100"></progress>
<progress class="progress progress-success w-56" value="70" max="100"></progress>
<progress class="progress progress-warning w-56" value="55" max="100"></progress>
<progress class="progress progress-error w-56" value="30" max="100"></progress>

<!-- Progress nieokreślony (animowany) -->
<progress class="progress w-56"></progress>

<!-- Radial progress -->
<div class="radial-progress" style="--value:70;">70%</div>
<div class="radial-progress" style="--value:70; --size:12rem; --thickness: 2px;">70%</div>
<div class="radial-progress bg-primary text-primary-content border-4 border-primary" style="--value:70;">70%</div>

<!-- Loading spinner -->
<span class="loading loading-spinner loading-xs"></span>
<span class="loading loading-spinner loading-sm"></span>
<span class="loading loading-spinner loading-md"></span>
<span class="loading loading-spinner loading-lg"></span>

<!-- Loading dots -->
<span class="loading loading-dots loading-lg"></span>

<!-- Loading ring -->
<span class="loading loading-ring loading-lg"></span>

<!-- Loading ball -->
<span class="loading loading-ball loading-lg"></span>

<!-- Loading bars -->
<span class="loading loading-bars loading-lg"></span>

<!-- Loading infinity -->
<span class="loading loading-infinity loading-lg"></span>

Avatar

Code
HTML
<!-- Podstawowy avatar -->
<div class="avatar">
  <div class="w-24 rounded">
    <img src="avatar.jpg" alt="Avatar" />
  </div>
</div>

<!-- Avatar zaokrąglony -->
<div class="avatar">
  <div class="w-24 rounded-full">
    <img src="avatar.jpg" alt="Avatar" />
  </div>
</div>

<!-- Avatar z mask -->
<div class="avatar">
  <div class="w-24 mask mask-squircle">
    <img src="avatar.jpg" alt="Avatar" />
  </div>
</div>

<div class="avatar">
  <div class="w-24 mask mask-hexagon">
    <img src="avatar.jpg" alt="Avatar" />
  </div>
</div>

<!-- Avatar z ringiem -->
<div class="avatar">
  <div class="w-24 rounded-full ring ring-primary ring-offset-base-100 ring-offset-2">
    <img src="avatar.jpg" alt="Avatar" />
  </div>
</div>

<!-- Avatar z online indicator -->
<div class="avatar online">
  <div class="w-24 rounded-full">
    <img src="avatar.jpg" alt="Avatar" />
  </div>
</div>

<div class="avatar offline">
  <div class="w-24 rounded-full">
    <img src="avatar.jpg" alt="Avatar" />
  </div>
</div>

<!-- Avatar placeholder -->
<div class="avatar placeholder">
  <div class="bg-neutral text-neutral-content rounded-full w-24">
    <span class="text-3xl">JK</span>
  </div>
</div>

<!-- Avatar group -->
<div class="avatar-group -space-x-6 rtl:space-x-reverse">
  <div class="avatar">
    <div class="w-12">
      <img src="avatar1.jpg" alt="Avatar 1" />
    </div>
  </div>
  <div class="avatar">
    <div class="w-12">
      <img src="avatar2.jpg" alt="Avatar 2" />
    </div>
  </div>
  <div class="avatar">
    <div class="w-12">
      <img src="avatar3.jpg" alt="Avatar 3" />
    </div>
  </div>
  <div class="avatar placeholder">
    <div class="w-12 bg-neutral text-neutral-content">
      <span>+99</span>
    </div>
  </div>
</div>

System tematów

Wbudowane tematy

DaisyUI oferuje 35+ gotowych tematów:

JStailwind.config.js
JavaScript
// tailwind.config.js
module.exports = {
  daisyui: {
    themes: [
      "light",
      "dark",
      "cupcake",
      "bumblebee",
      "emerald",
      "corporate",
      "synthwave",
      "retro",
      "cyberpunk",
      "valentine",
      "halloween",
      "garden",
      "forest",
      "aqua",
      "lofi",
      "pastel",
      "fantasy",
      "wireframe",
      "black",
      "luxury",
      "dracula",
      "cmyk",
      "autumn",
      "business",
      "acid",
      "lemonade",
      "night",
      "coffee",
      "winter",
      "dim",
      "nord",
      "sunset",
    ],
  },
}

Zmiana tematu

Code
HTML
<!-- W HTML -->
<html data-theme="cyberpunk">

<!-- Lub na konkretnym elemencie -->
<div data-theme="dark" class="bg-base-200 p-4">
  Ten div używa dark theme
</div>

Theme switcher w JavaScript

JSReact/Next.js
JavaScript
// React/Next.js przykład
import { useState, useEffect } from 'react'

export function ThemeSwitcher() {
  const [theme, setTheme] = useState('light')

  useEffect(() => {
    document.documentElement.setAttribute('data-theme', theme)
    localStorage.setItem('theme', theme)
  }, [theme])

  useEffect(() => {
    const savedTheme = localStorage.getItem('theme')
    if (savedTheme) {
      setTheme(savedTheme)
    }
  }, [])

  return (
    <select
      className="select select-bordered"
      value={theme}
      onChange={(e) => setTheme(e.target.value)}
    >
      <option value="light">Light</option>
      <option value="dark">Dark</option>
      <option value="cupcake">Cupcake</option>
      <option value="cyberpunk">Cyberpunk</option>
      <option value="synthwave">Synthwave</option>
    </select>
  )
}

Tworzenie własnego tematu

JStailwind.config.js
JavaScript
// tailwind.config.js
module.exports = {
  daisyui: {
    themes: [
      {
        mytheme: {
          "primary": "#a991f7",
          "primary-content": "#ffffff",
          "secondary": "#f6d860",
          "secondary-content": "#000000",
          "accent": "#37cdbe",
          "accent-content": "#000000",
          "neutral": "#3d4451",
          "neutral-content": "#ffffff",
          "base-100": "#ffffff",
          "base-200": "#f2f2f2",
          "base-300": "#e5e5e5",
          "base-content": "#1f2937",
          "info": "#3abff8",
          "success": "#36d399",
          "warning": "#fbbd23",
          "error": "#f87272",

          // Opcjonalne customizacje
          "--rounded-box": "1rem",
          "--rounded-btn": "0.5rem",
          "--rounded-badge": "1.9rem",
          "--animation-btn": "0.25s",
          "--animation-input": "0.2s",
          "--btn-focus-scale": "0.95",
          "--border-btn": "1px",
          "--tab-border": "1px",
          "--tab-radius": "0.5rem",
        },
      },
      "light",
      "dark",
    ],
  },
}

Kolory w tematach

Code
HTML
<!-- Kolory podstawowe -->
<div class="bg-primary text-primary-content">Primary</div>
<div class="bg-secondary text-secondary-content">Secondary</div>
<div class="bg-accent text-accent-content">Accent</div>
<div class="bg-neutral text-neutral-content">Neutral</div>

<!-- Kolory bazowe (tło) -->
<div class="bg-base-100">Base 100 (main bg)</div>
<div class="bg-base-200">Base 200 (slightly darker)</div>
<div class="bg-base-300">Base 300 (darker)</div>
<div class="text-base-content">Base content (text color)</div>

<!-- Kolory stanu -->
<div class="bg-info text-info-content">Info</div>
<div class="bg-success text-success-content">Success</div>
<div class="bg-warning text-warning-content">Warning</div>
<div class="bg-error text-error-content">Error</div>

Integracja z frameworkami

React / Next.js

TScomponents/Button.tsx
TypeScript
// components/Button.tsx
interface ButtonProps {
  variant?: 'primary' | 'secondary' | 'accent' | 'ghost'
  size?: 'lg' | 'md' | 'sm' | 'xs'
  children: React.ReactNode
  onClick?: () => void
  loading?: boolean
  disabled?: boolean
}

export function Button({
  variant = 'primary',
  size = 'md',
  children,
  onClick,
  loading = false,
  disabled = false,
}: ButtonProps) {
  return (
    <button
      className={`btn btn-${variant} btn-${size} ${loading ? 'loading' : ''}`}
      onClick={onClick}
      disabled={disabled || loading}
    >
      {children}
    </button>
  )
}

// Użycie
<Button variant="primary" size="lg" onClick={() => alert('Clicked!')}>
  Kliknij mnie
</Button>
TScomponents/Card.tsx
TypeScript
// components/Card.tsx
interface CardProps {
  title: string
  description?: string
  image?: string
  actions?: React.ReactNode
  compact?: boolean
}

export function Card({ title, description, image, actions, compact = false }: CardProps) {
  return (
    <div className={`card bg-base-100 shadow-xl ${compact ? 'card-compact' : ''}`}>
      {image && (
        <figure>
          <img src={image} alt={title} />
        </figure>
      )}
      <div className="card-body">
        <h2 className="card-title">{title}</h2>
        {description && <p>{description}</p>}
        {actions && <div className="card-actions justify-end">{actions}</div>}
      </div>
    </div>
  )
}

// Użycie
<Card
  title="Produkt"
  description="Opis produktu"
  image="/product.jpg"
  actions={<Button variant="primary">Kup</Button>}
/>
TScomponents/Modal.tsx
TypeScript
// components/Modal.tsx
import { useRef, useEffect } from 'react'

interface ModalProps {
  isOpen: boolean
  onClose: () => void
  title: string
  children: React.ReactNode
  actions?: React.ReactNode
}

export function Modal({ isOpen, onClose, title, children, actions }: ModalProps) {
  const dialogRef = useRef<HTMLDialogElement>(null)

  useEffect(() => {
    if (isOpen) {
      dialogRef.current?.showModal()
    } else {
      dialogRef.current?.close()
    }
  }, [isOpen])

  return (
    <dialog ref={dialogRef} className="modal" onClose={onClose}>
      <div className="modal-box">
        <button
          className="btn btn-sm btn-circle btn-ghost absolute right-2 top-2"
          onClick={onClose}
        >
        </button>
        <h3 className="font-bold text-lg">{title}</h3>
        <div className="py-4">{children}</div>
        {actions && <div className="modal-action">{actions}</div>}
      </div>
      <form method="dialog" className="modal-backdrop">
        <button onClick={onClose}>close</button>
      </form>
    </dialog>
  )
}

Vue 3

components/Button.vue
VUE
<!-- components/Button.vue -->
<script setup lang="ts">
interface Props {
  variant?: 'primary' | 'secondary' | 'accent' | 'ghost'
  size?: 'lg' | 'md' | 'sm' | 'xs'
  loading?: boolean
  disabled?: boolean
}

const props = withDefaults(defineProps<Props>(), {
  variant: 'primary',
  size: 'md',
  loading: false,
  disabled: false,
})

const emit = defineEmits(['click'])
</script>

<template>
  <button
    :class="[
      'btn',
      `btn-${variant}`,
      `btn-${size}`,
      { loading: loading }
    ]"
    :disabled="disabled || loading"
    @click="emit('click')"
  >
    <slot />
  </button>
</template>
components/ThemeSwitcher.vue
VUE
<!-- components/ThemeSwitcher.vue -->
<script setup lang="ts">
import { ref, onMounted, watch } from 'vue'

const themes = ['light', 'dark', 'cupcake', 'cyberpunk', 'synthwave']
const currentTheme = ref('light')

onMounted(() => {
  const saved = localStorage.getItem('theme')
  if (saved) {
    currentTheme.value = saved
    document.documentElement.setAttribute('data-theme', saved)
  }
})

watch(currentTheme, (newTheme) => {
  document.documentElement.setAttribute('data-theme', newTheme)
  localStorage.setItem('theme', newTheme)
})
</script>

<template>
  <select v-model="currentTheme" class="select select-bordered">
    <option v-for="theme in themes" :key="theme" :value="theme">
      {{ theme }}
    </option>
  </select>
</template>

Svelte

Button.svelte
SVELTE
<!-- Button.svelte -->
<script lang="ts">
  export let variant: 'primary' | 'secondary' | 'accent' | 'ghost' = 'primary'
  export let size: 'lg' | 'md' | 'sm' | 'xs' = 'md'
  export let loading = false
  export let disabled = false
</script>

<button
  class="btn btn-{variant} btn-{size}"
  class:loading
  disabled={disabled || loading}
  on:click
>
  <slot />
</button>
ThemeSwitcher.svelte
SVELTE
<!-- ThemeSwitcher.svelte -->
<script lang="ts">
  import { onMount } from 'svelte'

  const themes = ['light', 'dark', 'cupcake', 'cyberpunk', 'synthwave']
  let currentTheme = 'light'

  onMount(() => {
    const saved = localStorage.getItem('theme')
    if (saved) {
      currentTheme = saved
      document.documentElement.setAttribute('data-theme', saved)
    }
  })

  function handleChange(event: Event) {
    const target = event.target as HTMLSelectElement
    currentTheme = target.value
    document.documentElement.setAttribute('data-theme', currentTheme)
    localStorage.setItem('theme', currentTheme)
  }
</script>

<select class="select select-bordered" value={currentTheme} on:change={handleChange}>
  {#each themes as theme}
    <option value={theme}>{theme}</option>
  {/each}
</select>

Responsywność

Breakpoints z Tailwind

Code
HTML
<!-- Karty responsywne -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
  <div class="card bg-base-100 shadow-xl">
    <div class="card-body">
      <h2 class="card-title">Card 1</h2>
    </div>
  </div>
  <div class="card bg-base-100 shadow-xl">
    <div class="card-body">
      <h2 class="card-title">Card 2</h2>
    </div>
  </div>
  <div class="card bg-base-100 shadow-xl">
    <div class="card-body">
      <h2 class="card-title">Card 3</h2>
    </div>
  </div>
</div>

<!-- Przyciski responsywne -->
<button class="btn btn-sm md:btn-md lg:btn-lg">
  Responsywny przycisk
</button>

<!-- Drawer responsywny -->
<div class="drawer lg:drawer-open">
  <input id="my-drawer" type="checkbox" class="drawer-toggle" />
  <div class="drawer-content">
    <!-- Page content -->
    <label for="my-drawer" class="btn btn-primary drawer-button lg:hidden">
      Open drawer
    </label>
  </div>
  <div class="drawer-side">
    <label for="my-drawer" aria-label="close sidebar" class="drawer-overlay"></label>
    <ul class="menu p-4 w-80 min-h-full bg-base-200">
      <li><a>Sidebar Item 1</a></li>
      <li><a>Sidebar Item 2</a></li>
    </ul>
  </div>
</div>

Dostępność (Accessibility)

ARIA attributes

Code
HTML
<!-- Przycisk z ARIA -->
<button class="btn btn-primary" aria-label="Zapisz dokument">
  <svg>...</svg>
  Zapisz
</button>

<!-- Modal z ARIA -->
<dialog id="modal" class="modal" aria-labelledby="modal-title" aria-describedby="modal-desc">
  <div class="modal-box">
    <h3 id="modal-title" class="font-bold text-lg">Tytuł</h3>
    <p id="modal-desc" class="py-4">Opis modala</p>
  </div>
</dialog>

<!-- Tabs z rolami -->
<div role="tablist" class="tabs tabs-boxed" aria-label="Navigation tabs">
  <button role="tab" class="tab" aria-selected="false">Tab 1</button>
  <button role="tab" class="tab tab-active" aria-selected="true">Tab 2</button>
  <button role="tab" class="tab" aria-selected="false">Tab 3</button>
</div>

<!-- Alert z role -->
<div role="alert" class="alert alert-warning">
  <span>Uwaga: Sprawdź swoje dane</span>
</div>

<!-- Progress z ARIA -->
<progress
  class="progress progress-primary w-56"
  value="70"
  max="100"
  aria-label="Postęp ładowania"
  aria-valuenow="70"
  aria-valuemin="0"
  aria-valuemax="100"
></progress>

Fokus i nawigacja klawiaturą

Code
HTML
<!-- Skip link -->
<a href="#main-content" class="btn btn-link sr-only focus:not-sr-only">
  Przejdź do głównej treści
</a>

<!-- Focus ring -->
<button class="btn btn-primary focus:ring focus:ring-primary focus:ring-offset-2">
  Widoczny focus
</button>

<!-- Focusable card -->
<div class="card bg-base-100 shadow-xl" tabindex="0" role="article">
  <div class="card-body">
    <h2 class="card-title">Focusable Card</h2>
    <p>Można nawigować Tab-em</p>
  </div>
</div>

Optymalizacja wydajności

Purge nieużywanych klas

JStailwind.config.js
JavaScript
// tailwind.config.js
module.exports = {
  content: [
    "./src/**/*.{js,ts,jsx,tsx,html}",
  ],
  theme: {
    extend: {},
  },
  plugins: [require("daisyui")],
  daisyui: {
    themes: ["light", "dark"], // Tylko używane tematy
    styled: true,
    base: true,
    utils: true,
    logs: false, // Wyłącz logi w produkcji
  },
}

Lazy loading komponentów

Code
TypeScript
// React - dynamiczny import modala
import dynamic from 'next/dynamic'

const Modal = dynamic(() => import('./Modal'), {
  loading: () => <span className="loading loading-spinner" />,
  ssr: false
})

Minimalizacja CSS

Code
Bash
# Budowanie z minifikacją
NODE_ENV=production npx tailwindcss -i ./src/input.css -o ./dist/output.css --minify

Best practices

Struktura projektu

Code
TEXT
src/
├── components/
│   ├── ui/           # Podstawowe komponenty DaisyUI
│   │   ├── Button.tsx
│   │   ├── Card.tsx
│   │   ├── Modal.tsx
│   │   └── Input.tsx
│   ├── layout/       # Layouty
│   │   ├── Navbar.tsx
│   │   ├── Sidebar.tsx
│   │   └── Footer.tsx
│   └── features/     # Komponenty biznesowe
├── styles/
│   └── globals.css   # Import Tailwind
└── lib/
    └── theme.ts      # Konfiguracja tematów

Konsystencja w projekcie

TSlib/theme.ts
TypeScript
// lib/theme.ts - Centralizacja kolorów i wariantów
export const buttonVariants = {
  primary: 'btn-primary',
  secondary: 'btn-secondary',
  danger: 'btn-error',
  success: 'btn-success',
} as const

export const sizeVariants = {
  small: 'btn-sm',
  medium: 'btn-md',
  large: 'btn-lg',
} as const

// Użycie
<button className={`btn ${buttonVariants.primary} ${sizeVariants.medium}`}>
  Przycisk
</button>

Łączenie z Tailwind utilities

Code
HTML
<!-- DaisyUI + Tailwind utilities -->
<button class="btn btn-primary hover:scale-105 transition-transform">
  Animowany przycisk
</button>

<div class="card bg-base-100 shadow-xl hover:shadow-2xl transition-shadow">
  <div class="card-body">
    <h2 class="card-title text-gradient">Gradient title</h2>
  </div>
</div>

<input
  class="input input-bordered focus:input-primary w-full"
  placeholder="Focus zmienia kolor"
/>

FAQ - Najczęściej zadawane pytania

Czy DaisyUI zwiększa rozmiar bundle?

Nie znacząco. DaisyUI to czysty CSS, który jest purgowany przez Tailwind w produkcji. Używane komponenty dodają minimalny overhead. W praktyce często zmniejsza bundle, bo używasz krótszych klas (btn zamiast 10 utility classes).

Czy mogę używać DaisyUI z komponentami JavaScript?

Tak! DaisyUI to tylko CSS - nie wymaga żadnego JavaScript. Możesz dodać własną logikę lub użyć bibliotek jak Headless UI dla bardziej złożonych interakcji (dropdown, modal z focus trap itp.).

Jak customizować istniejące komponenty?

Masz trzy opcje:

  1. Dodaj klasy Tailwind obok klas DaisyUI
  2. Stwórz własny temat z custom colors
  3. Nadpisz style w CSS używając selektorów

Czy DaisyUI jest kompatybilny z Tailwind v4?

Tak! DaisyUI wspiera Tailwind v4. Sprawdź dokumentację dla szczegółów konfiguracji.

Jak zaimplementować dark mode?

DaisyUI ma wbudowane wsparcie przez tematy. Ustaw data-theme="dark" na <html> i używaj tematu "dark" lub dowolnego ciemnego tematu jak "dracula", "night", "forest".

Podsumowanie

DaisyUI to idealne rozwiązanie dla projektów używających Tailwind CSS, oferujące:

  • Semantyczne klasy - Czytelniejszy kod, szybsze pisanie
  • 35+ tematów - Łatwa zmiana wyglądu całej aplikacji
  • 50+ komponentów - Wszystko czego potrzebujesz do UI
  • Zero JavaScript - Działa z każdym frameworkiem
  • Pełna kompatybilność - Z Tailwind utilities i responsive design
  • 100% darmowy - Open source, MIT License

Jeśli używasz Tailwind CSS i chcesz przyspieszyć development bez rezygnacji z elastyczności, DaisyUI jest doskonałym wyborem.


DaisyUI - A complete guide to components for Tailwind CSS

What is DaisyUI?

DaisyUI is the most popular Tailwind CSS plugin that adds ready-made component classes to your project. Instead of writing dozens of utility classes like bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-4 rounded, you simply write btn btn-primary. It is the best thing that could have happened to Tailwind CSS.

DaisyUI does not replace Tailwind - it extends it. You can still use all Tailwind utility classes alongside DaisyUI semantic classes. This gives you the flexibility of Tailwind with the convenience of ready-made components, and all of it without any JavaScript - DaisyUI is pure CSS.

Why DaisyUI?

Key advantages of DaisyUI

  1. Semantic classes - btn instead of bg-blue-500 hover:bg-blue-600...
  2. 35+ themes - Easy appearance change for your entire application
  3. Zero JavaScript - Pure CSS, works with any framework
  4. Full compatibility - Works with React, Vue, Svelte, Angular, vanilla HTML
  5. Smaller bundle - Fewer classes = smaller CSS
  6. 100% free - MIT License, open source

DaisyUI vs other solutions

FeatureDaisyUITailwind UIHeadless UIBootstrap
PriceFree$299+FreeFree
JavaScriptNot requiredYesYesYes
TailwindNativeNativeNativeSeparate
Components50+500+1025+
Themes35+NoneNoneLimited
CustomizationFullFullFullLimited
Bundle sizeMinimalMediumMinimalLarge

Installation and configuration

npm installation

Code
Bash
# npm
npm install -D daisyui@latest

# pnpm
pnpm add -D daisyui@latest

# yarn
yarn add -D daisyui@latest

# bun
bun add -D daisyui@latest

Tailwind CSS v3 configuration

JStailwind.config.js
JavaScript
// tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    "./src/**/*.{js,ts,jsx,tsx,html}",
    "./components/**/*.{js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [
    require("daisyui"),
  ],
  daisyui: {
    themes: ["light", "dark", "cupcake", "cyberpunk", "valentine", "forest"],
    darkTheme: "dark",
    base: true,
    styled: true,
    utils: true,
    prefix: "",
    logs: true,
    themeRoot: ":root",
  },
}

Tailwind CSS v4 configuration

JStailwind.config.js
JavaScript
// tailwind.config.js (v4)
import daisyui from "daisyui"

export default {
  plugins: [daisyui],
  daisyui: {
    themes: ["light", "dark"],
  },
}

Verifying the installation

Code
HTML
<!-- Check if DaisyUI is working -->
<button class="btn btn-primary">
  If this button is styled, DaisyUI is working!
</button>

DaisyUI components

Buttons (Button)

Code
HTML
<!-- Basic variants -->
<button class="btn">Default</button>
<button class="btn btn-neutral">Neutral</button>
<button class="btn btn-primary">Primary</button>
<button class="btn btn-secondary">Secondary</button>
<button class="btn btn-accent">Accent</button>
<button class="btn btn-ghost">Ghost</button>
<button class="btn btn-link">Link</button>

<!-- States -->
<button class="btn btn-info">Info</button>
<button class="btn btn-success">Success</button>
<button class="btn btn-warning">Warning</button>
<button class="btn btn-error">Error</button>

<!-- Sizes -->
<button class="btn btn-lg">Large</button>
<button class="btn btn-md">Medium (default)</button>
<button class="btn btn-sm">Small</button>
<button class="btn btn-xs">Extra small</button>

<!-- Modifiers -->
<button class="btn btn-wide">Wide</button>
<button class="btn btn-block">Block (full width)</button>
<button class="btn btn-circle"></button>
<button class="btn btn-square"></button>

<!-- Interactive states -->
<button class="btn btn-outline btn-primary">Outline</button>
<button class="btn btn-active">Active</button>
<button class="btn btn-disabled">Disabled</button>
<button class="btn loading">Loading...</button>

<!-- With icon -->
<button class="btn btn-primary gap-2">
  <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
    <path d="M10 12a2 2 0 100-4 2 2 0 000 4z" />
  </svg>
  Settings
</button>

Cards (Card)

Code
HTML
<!-- Basic card -->
<div class="card w-96 bg-base-100 shadow-xl">
  <figure>
    <img src="https://picsum.photos/400/200" alt="Image" />
  </figure>
  <div class="card-body">
    <h2 class="card-title">Card title</h2>
    <p>Card description with additional text explaining the content.</p>
    <div class="card-actions justify-end">
      <button class="btn btn-primary">Buy now</button>
    </div>
  </div>
</div>

<!-- Compact card -->
<div class="card card-compact w-96 bg-base-100 shadow-xl">
  <figure><img src="image.jpg" alt="Photo" /></figure>
  <div class="card-body">
    <h2 class="card-title">Compact!</h2>
    <p>Less padding</p>
    <div class="card-actions justify-end">
      <button class="btn btn-primary btn-sm">Action</button>
    </div>
  </div>
</div>

<!-- Card with badge -->
<div class="card w-96 bg-base-100 shadow-xl">
  <div class="card-body">
    <h2 class="card-title">
      Product
      <div class="badge badge-secondary">NEW</div>
    </h2>
    <p>Product description</p>
    <div class="card-actions justify-end">
      <div class="badge badge-outline">Fashion</div>
      <div class="badge badge-outline">Products</div>
    </div>
  </div>
</div>

<!-- Horizontal card -->
<div class="card card-side bg-base-100 shadow-xl">
  <figure><img src="image.jpg" alt="Movie" class="w-48" /></figure>
  <div class="card-body">
    <h2 class="card-title">Movie</h2>
    <p>Movie description</p>
    <div class="card-actions justify-end">
      <button class="btn btn-primary">Watch</button>
    </div>
  </div>
</div>

<!-- Card with overlay -->
<div class="card w-96 bg-base-100 shadow-xl image-full">
  <figure><img src="background.jpg" alt="Background" /></figure>
  <div class="card-body">
    <h2 class="card-title">Title</h2>
    <p>Text over the background image</p>
    <div class="card-actions justify-end">
      <button class="btn btn-primary">Action</button>
    </div>
  </div>
</div>

Modal

Code
HTML
<!-- Modal with button -->
<button class="btn" onclick="my_modal_1.showModal()">Open Modal</button>

<dialog id="my_modal_1" class="modal">
  <div class="modal-box">
    <h3 class="font-bold text-lg">Hello!</h3>
    <p class="py-4">Press ESC or click the button to close</p>
    <div class="modal-action">
      <form method="dialog">
        <button class="btn">Close</button>
      </form>
    </div>
  </div>
</dialog>

<!-- Modal with backdrop to close -->
<button class="btn" onclick="my_modal_2.showModal()">Modal with backdrop</button>

<dialog id="my_modal_2" class="modal">
  <div class="modal-box">
    <h3 class="font-bold text-lg">Modal</h3>
    <p class="py-4">Click outside the modal to close</p>
  </div>
  <form method="dialog" class="modal-backdrop">
    <button>close</button>
  </form>
</dialog>

<!-- Modal with actions -->
<dialog id="my_modal_3" class="modal">
  <div class="modal-box">
    <form method="dialog">
      <button class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2"></button>
    </form>
    <h3 class="font-bold text-lg">Confirm action</h3>
    <p class="py-4">Are you sure you want to continue?</p>
    <div class="modal-action">
      <form method="dialog">
        <button class="btn btn-ghost">Cancel</button>
        <button class="btn btn-primary">Confirm</button>
      </form>
    </div>
  </div>
</dialog>

Navigation (Navbar)

Code
HTML
<!-- Simple navbar -->
<div class="navbar bg-base-100">
  <a class="btn btn-ghost text-xl">daisyUI</a>
</div>

<!-- Navbar with menu -->
<div class="navbar bg-base-100">
  <div class="flex-1">
    <a class="btn btn-ghost text-xl">Logo</a>
  </div>
  <div class="flex-none">
    <ul class="menu menu-horizontal px-1">
      <li><a>Link 1</a></li>
      <li><a>Link 2</a></li>
    </ul>
  </div>
</div>

<!-- Navbar with search and avatar -->
<div class="navbar bg-base-100">
  <div class="flex-1">
    <a class="btn btn-ghost text-xl">Logo</a>
  </div>
  <div class="flex-none gap-2">
    <div class="form-control">
      <input type="text" placeholder="Search" class="input input-bordered w-24 md:w-auto" />
    </div>
    <div class="dropdown dropdown-end">
      <div tabindex="0" role="button" class="btn btn-ghost btn-circle avatar">
        <div class="w-10 rounded-full">
          <img alt="Avatar" src="avatar.jpg" />
        </div>
      </div>
      <ul tabindex="0" class="mt-3 z-[1] p-2 shadow menu menu-sm dropdown-content bg-base-100 rounded-box w-52">
        <li><a>Profile</a></li>
        <li><a>Settings</a></li>
        <li><a>Logout</a></li>
      </ul>
    </div>
  </div>
</div>

<!-- Navbar with icons -->
<div class="navbar bg-neutral text-neutral-content">
  <div class="flex-1">
    <a class="btn btn-ghost text-xl">daisyUI</a>
  </div>
  <div class="flex-none">
    <button class="btn btn-square btn-ghost">
      <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="inline-block w-5 h-5 stroke-current">
        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 12h.01M12 12h.01M19 12h.01M6 12a1 1 0 11-2 0 1 1 0 012 0zm7 0a1 1 0 11-2 0 1 1 0 012 0zm7 0a1 1 0 11-2 0 1 1 0 012 0z"></path>
      </svg>
    </button>
  </div>
</div>

Forms

Code
HTML
<!-- Input -->
<div class="form-control w-full max-w-xs">
  <label class="label">
    <span class="label-text">Email</span>
    <span class="label-text-alt">Required</span>
  </label>
  <input type="email" placeholder="email@example.com" class="input input-bordered w-full max-w-xs" />
  <label class="label">
    <span class="label-text-alt">Enter a valid email address</span>
  </label>
</div>

<!-- Input with variants -->
<input type="text" placeholder="Default" class="input input-bordered w-full max-w-xs" />
<input type="text" placeholder="Primary" class="input input-bordered input-primary w-full max-w-xs" />
<input type="text" placeholder="Secondary" class="input input-bordered input-secondary w-full max-w-xs" />
<input type="text" placeholder="Accent" class="input input-bordered input-accent w-full max-w-xs" />
<input type="text" placeholder="Info" class="input input-bordered input-info w-full max-w-xs" />
<input type="text" placeholder="Success" class="input input-bordered input-success w-full max-w-xs" />
<input type="text" placeholder="Warning" class="input input-bordered input-warning w-full max-w-xs" />
<input type="text" placeholder="Error" class="input input-bordered input-error w-full max-w-xs" />

<!-- Sizes -->
<input type="text" placeholder="Large" class="input input-bordered input-lg" />
<input type="text" placeholder="Medium" class="input input-bordered input-md" />
<input type="text" placeholder="Small" class="input input-bordered input-sm" />
<input type="text" placeholder="XS" class="input input-bordered input-xs" />

<!-- Select -->
<select class="select select-bordered w-full max-w-xs">
  <option disabled selected>Choose an option</option>
  <option>Option 1</option>
  <option>Option 2</option>
  <option>Option 3</option>
</select>

<!-- Textarea -->
<textarea class="textarea textarea-bordered" placeholder="Your message"></textarea>

<!-- Checkbox -->
<div class="form-control">
  <label class="label cursor-pointer">
    <span class="label-text">Remember me</span>
    <input type="checkbox" checked class="checkbox checkbox-primary" />
  </label>
</div>

<!-- Radio -->
<div class="form-control">
  <label class="label cursor-pointer">
    <span class="label-text">Option A</span>
    <input type="radio" name="radio-1" class="radio radio-primary" checked />
  </label>
  <label class="label cursor-pointer">
    <span class="label-text">Option B</span>
    <input type="radio" name="radio-1" class="radio radio-primary" />
  </label>
</div>

<!-- Toggle -->
<input type="checkbox" class="toggle toggle-primary" checked />

<!-- Range -->
<input type="range" min="0" max="100" value="40" class="range range-primary" />

<!-- Rating -->
<div class="rating">
  <input type="radio" name="rating-1" class="mask mask-star" />
  <input type="radio" name="rating-1" class="mask mask-star" checked />
  <input type="radio" name="rating-1" class="mask mask-star" />
  <input type="radio" name="rating-1" class="mask mask-star" />
  <input type="radio" name="rating-1" class="mask mask-star" />
</div>

<!-- File input -->
<input type="file" class="file-input file-input-bordered w-full max-w-xs" />

Tables

Code
HTML
<!-- Basic table -->
<div class="overflow-x-auto">
  <table class="table">
    <thead>
      <tr>
        <th></th>
        <th>Name</th>
        <th>Position</th>
        <th>Email</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <th>1</th>
        <td>John Smith</td>
        <td>Developer</td>
        <td>john@example.com</td>
      </tr>
      <tr>
        <th>2</th>
        <td>Anna Johnson</td>
        <td>Designer</td>
        <td>anna@example.com</td>
      </tr>
      <tr>
        <th>3</th>
        <td>Peter Williams</td>
        <td>Manager</td>
        <td>peter@example.com</td>
      </tr>
    </tbody>
  </table>
</div>

<!-- Zebra table -->
<table class="table table-zebra">
  <!-- ... -->
</table>

<!-- Table with hover -->
<table class="table">
  <tbody>
    <tr class="hover">
      <td>Row with hover effect</td>
    </tr>
  </tbody>
</table>

<!-- Active table -->
<table class="table">
  <tbody>
    <tr class="active">
      <td>Active row (highlighted)</td>
    </tr>
  </tbody>
</table>

<!-- Compact table -->
<table class="table table-xs">
  <!-- Less padding -->
</table>

Alerts and notifications

Code
HTML
<!-- Basic alert -->
<div class="alert">
  <span>12 unread messages.</span>
</div>

<!-- Info alert -->
<div class="alert alert-info">
  <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="stroke-current shrink-0 w-6 h-6">
    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
  </svg>
  <span>A new software update is available.</span>
</div>

<!-- Success alert -->
<div class="alert alert-success">
  <svg xmlns="http://www.w3.org/2000/svg" class="stroke-current shrink-0 h-6 w-6" fill="none" viewBox="0 0 24 24">
    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
  </svg>
  <span>Your order has been confirmed!</span>
</div>

<!-- Warning alert -->
<div class="alert alert-warning">
  <svg xmlns="http://www.w3.org/2000/svg" class="stroke-current shrink-0 h-6 w-6" fill="none" viewBox="0 0 24 24">
    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
  </svg>
  <span>Warning: Your session expires in 5 minutes!</span>
</div>

<!-- Error alert -->
<div class="alert alert-error">
  <svg xmlns="http://www.w3.org/2000/svg" class="stroke-current shrink-0 h-6 w-6" fill="none" viewBox="0 0 24 24">
    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z" />
  </svg>
  <span>Error! Something went wrong.</span>
</div>

<!-- Alert with actions -->
<div class="alert">
  <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="stroke-info shrink-0 w-6 h-6">
    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
  </svg>
  <span>We have new terms of service.</span>
  <div>
    <button class="btn btn-sm">Decline</button>
    <button class="btn btn-sm btn-primary">Accept</button>
  </div>
</div>

<!-- Toast -->
<div class="toast toast-end">
  <div class="alert alert-info">
    <span>New message.</span>
  </div>
</div>

Badge and Indicator

Code
HTML
<!-- Badge -->
<span class="badge">default</span>
<span class="badge badge-neutral">neutral</span>
<span class="badge badge-primary">primary</span>
<span class="badge badge-secondary">secondary</span>
<span class="badge badge-accent">accent</span>
<span class="badge badge-ghost">ghost</span>

<!-- Badge outline -->
<span class="badge badge-outline">outline</span>
<span class="badge badge-outline badge-primary">primary</span>

<!-- Badge sizes -->
<span class="badge badge-lg">Large</span>
<span class="badge badge-md">Medium</span>
<span class="badge badge-sm">Small</span>
<span class="badge badge-xs">Tiny</span>

<!-- Badge in button -->
<button class="btn gap-2">
  Inbox
  <span class="badge badge-sm">+99</span>
</button>

<!-- Indicator -->
<div class="indicator">
  <span class="indicator-item badge badge-primary">new</span>
  <div class="grid w-32 h-32 bg-base-300 place-items-center">content</div>
</div>

<!-- Indicator on avatar -->
<div class="indicator">
  <span class="indicator-item badge badge-secondary">online</span>
  <div class="avatar">
    <div class="w-12 rounded">
      <img src="avatar.jpg" alt="Avatar" />
    </div>
  </div>
</div>

Collapse and Accordion

Code
HTML
<!-- Collapse -->
<div class="collapse bg-base-200">
  <input type="checkbox" />
  <div class="collapse-title text-xl font-medium">
    Click to expand
  </div>
  <div class="collapse-content">
    <p>Hidden content appears after clicking.</p>
  </div>
</div>

<!-- Collapse with arrow -->
<div class="collapse collapse-arrow bg-base-200">
  <input type="checkbox" />
  <div class="collapse-title text-xl font-medium">
    Click to expand
  </div>
  <div class="collapse-content">
    <p>Content with arrow icon.</p>
  </div>
</div>

<!-- Collapse with plus -->
<div class="collapse collapse-plus bg-base-200">
  <input type="checkbox" />
  <div class="collapse-title text-xl font-medium">
    Click to expand
  </div>
  <div class="collapse-content">
    <p>Content with plus/minus icon.</p>
  </div>
</div>

<!-- Accordion (radio - only one open at a time) -->
<div class="join join-vertical w-full">
  <div class="collapse collapse-arrow join-item border border-base-300">
    <input type="radio" name="my-accordion-1" checked />
    <div class="collapse-title text-xl font-medium">
      Question 1
    </div>
    <div class="collapse-content">
      <p>Answer to question 1.</p>
    </div>
  </div>
  <div class="collapse collapse-arrow join-item border border-base-300">
    <input type="radio" name="my-accordion-1" />
    <div class="collapse-title text-xl font-medium">
      Question 2
    </div>
    <div class="collapse-content">
      <p>Answer to question 2.</p>
    </div>
  </div>
  <div class="collapse collapse-arrow join-item border border-base-300">
    <input type="radio" name="my-accordion-1" />
    <div class="collapse-title text-xl font-medium">
      Question 3
    </div>
    <div class="collapse-content">
      <p>Answer to question 3.</p>
    </div>
  </div>
</div>

Tabs

Code
HTML
<!-- Basic tabs -->
<div role="tablist" class="tabs tabs-bordered">
  <a role="tab" class="tab">Tab 1</a>
  <a role="tab" class="tab tab-active">Tab 2</a>
  <a role="tab" class="tab">Tab 3</a>
</div>

<!-- Tabs lifted -->
<div role="tablist" class="tabs tabs-lifted">
  <a role="tab" class="tab">Tab 1</a>
  <a role="tab" class="tab tab-active">Tab 2</a>
  <a role="tab" class="tab">Tab 3</a>
</div>

<!-- Tabs boxed -->
<div role="tablist" class="tabs tabs-boxed">
  <a role="tab" class="tab">Tab 1</a>
  <a role="tab" class="tab tab-active">Tab 2</a>
  <a role="tab" class="tab">Tab 3</a>
</div>

<!-- Tabs with content (radio) -->
<div role="tablist" class="tabs tabs-lifted">
  <input type="radio" name="my_tabs_1" role="tab" class="tab" aria-label="Tab 1" />
  <div role="tabpanel" class="tab-content bg-base-100 border-base-300 rounded-box p-6">
    Tab 1 content
  </div>

  <input type="radio" name="my_tabs_1" role="tab" class="tab" aria-label="Tab 2" checked />
  <div role="tabpanel" class="tab-content bg-base-100 border-base-300 rounded-box p-6">
    Tab 2 content
  </div>

  <input type="radio" name="my_tabs_1" role="tab" class="tab" aria-label="Tab 3" />
  <div role="tabpanel" class="tab-content bg-base-100 border-base-300 rounded-box p-6">
    Tab 3 content
  </div>
</div>

Progress and Loading

Code
HTML
<!-- Progress bar -->
<progress class="progress w-56" value="0" max="100"></progress>
<progress class="progress w-56" value="25" max="100"></progress>
<progress class="progress w-56" value="50" max="100"></progress>
<progress class="progress w-56" value="75" max="100"></progress>
<progress class="progress w-56" value="100" max="100"></progress>

<!-- Progress with colors -->
<progress class="progress progress-primary w-56" value="40" max="100"></progress>
<progress class="progress progress-secondary w-56" value="60" max="100"></progress>
<progress class="progress progress-accent w-56" value="80" max="100"></progress>
<progress class="progress progress-info w-56" value="45" max="100"></progress>
<progress class="progress progress-success w-56" value="70" max="100"></progress>
<progress class="progress progress-warning w-56" value="55" max="100"></progress>
<progress class="progress progress-error w-56" value="30" max="100"></progress>

<!-- Indeterminate progress (animated) -->
<progress class="progress w-56"></progress>

<!-- Radial progress -->
<div class="radial-progress" style="--value:70;">70%</div>
<div class="radial-progress" style="--value:70; --size:12rem; --thickness: 2px;">70%</div>
<div class="radial-progress bg-primary text-primary-content border-4 border-primary" style="--value:70;">70%</div>

<!-- Loading spinner -->
<span class="loading loading-spinner loading-xs"></span>
<span class="loading loading-spinner loading-sm"></span>
<span class="loading loading-spinner loading-md"></span>
<span class="loading loading-spinner loading-lg"></span>

<!-- Loading dots -->
<span class="loading loading-dots loading-lg"></span>

<!-- Loading ring -->
<span class="loading loading-ring loading-lg"></span>

<!-- Loading ball -->
<span class="loading loading-ball loading-lg"></span>

<!-- Loading bars -->
<span class="loading loading-bars loading-lg"></span>

<!-- Loading infinity -->
<span class="loading loading-infinity loading-lg"></span>

Avatar

Code
HTML
<!-- Basic avatar -->
<div class="avatar">
  <div class="w-24 rounded">
    <img src="avatar.jpg" alt="Avatar" />
  </div>
</div>

<!-- Rounded avatar -->
<div class="avatar">
  <div class="w-24 rounded-full">
    <img src="avatar.jpg" alt="Avatar" />
  </div>
</div>

<!-- Avatar with mask -->
<div class="avatar">
  <div class="w-24 mask mask-squircle">
    <img src="avatar.jpg" alt="Avatar" />
  </div>
</div>

<div class="avatar">
  <div class="w-24 mask mask-hexagon">
    <img src="avatar.jpg" alt="Avatar" />
  </div>
</div>

<!-- Avatar with ring -->
<div class="avatar">
  <div class="w-24 rounded-full ring ring-primary ring-offset-base-100 ring-offset-2">
    <img src="avatar.jpg" alt="Avatar" />
  </div>
</div>

<!-- Avatar with online indicator -->
<div class="avatar online">
  <div class="w-24 rounded-full">
    <img src="avatar.jpg" alt="Avatar" />
  </div>
</div>

<div class="avatar offline">
  <div class="w-24 rounded-full">
    <img src="avatar.jpg" alt="Avatar" />
  </div>
</div>

<!-- Avatar placeholder -->
<div class="avatar placeholder">
  <div class="bg-neutral text-neutral-content rounded-full w-24">
    <span class="text-3xl">JK</span>
  </div>
</div>

<!-- Avatar group -->
<div class="avatar-group -space-x-6 rtl:space-x-reverse">
  <div class="avatar">
    <div class="w-12">
      <img src="avatar1.jpg" alt="Avatar 1" />
    </div>
  </div>
  <div class="avatar">
    <div class="w-12">
      <img src="avatar2.jpg" alt="Avatar 2" />
    </div>
  </div>
  <div class="avatar">
    <div class="w-12">
      <img src="avatar3.jpg" alt="Avatar 3" />
    </div>
  </div>
  <div class="avatar placeholder">
    <div class="w-12 bg-neutral text-neutral-content">
      <span>+99</span>
    </div>
  </div>
</div>

Theme system

Built-in themes

DaisyUI offers 35+ ready-made themes:

JStailwind.config.js
JavaScript
// tailwind.config.js
module.exports = {
  daisyui: {
    themes: [
      "light",
      "dark",
      "cupcake",
      "bumblebee",
      "emerald",
      "corporate",
      "synthwave",
      "retro",
      "cyberpunk",
      "valentine",
      "halloween",
      "garden",
      "forest",
      "aqua",
      "lofi",
      "pastel",
      "fantasy",
      "wireframe",
      "black",
      "luxury",
      "dracula",
      "cmyk",
      "autumn",
      "business",
      "acid",
      "lemonade",
      "night",
      "coffee",
      "winter",
      "dim",
      "nord",
      "sunset",
    ],
  },
}

Changing the theme

Code
HTML
<!-- In HTML -->
<html data-theme="cyberpunk">

<!-- Or on a specific element -->
<div data-theme="dark" class="bg-base-200 p-4">
  This div uses the dark theme
</div>

Theme switcher in JavaScript

JSReact/Next.js
JavaScript
// React/Next.js example
import { useState, useEffect } from 'react'

export function ThemeSwitcher() {
  const [theme, setTheme] = useState('light')

  useEffect(() => {
    document.documentElement.setAttribute('data-theme', theme)
    localStorage.setItem('theme', theme)
  }, [theme])

  useEffect(() => {
    const savedTheme = localStorage.getItem('theme')
    if (savedTheme) {
      setTheme(savedTheme)
    }
  }, [])

  return (
    <select
      className="select select-bordered"
      value={theme}
      onChange={(e) => setTheme(e.target.value)}
    >
      <option value="light">Light</option>
      <option value="dark">Dark</option>
      <option value="cupcake">Cupcake</option>
      <option value="cyberpunk">Cyberpunk</option>
      <option value="synthwave">Synthwave</option>
    </select>
  )
}

Creating a custom theme

JStailwind.config.js
JavaScript
// tailwind.config.js
module.exports = {
  daisyui: {
    themes: [
      {
        mytheme: {
          "primary": "#a991f7",
          "primary-content": "#ffffff",
          "secondary": "#f6d860",
          "secondary-content": "#000000",
          "accent": "#37cdbe",
          "accent-content": "#000000",
          "neutral": "#3d4451",
          "neutral-content": "#ffffff",
          "base-100": "#ffffff",
          "base-200": "#f2f2f2",
          "base-300": "#e5e5e5",
          "base-content": "#1f2937",
          "info": "#3abff8",
          "success": "#36d399",
          "warning": "#fbbd23",
          "error": "#f87272",

          // Optional customizations
          "--rounded-box": "1rem",
          "--rounded-btn": "0.5rem",
          "--rounded-badge": "1.9rem",
          "--animation-btn": "0.25s",
          "--animation-input": "0.2s",
          "--btn-focus-scale": "0.95",
          "--border-btn": "1px",
          "--tab-border": "1px",
          "--tab-radius": "0.5rem",
        },
      },
      "light",
      "dark",
    ],
  },
}

Colors in themes

Code
HTML
<!-- Primary colors -->
<div class="bg-primary text-primary-content">Primary</div>
<div class="bg-secondary text-secondary-content">Secondary</div>
<div class="bg-accent text-accent-content">Accent</div>
<div class="bg-neutral text-neutral-content">Neutral</div>

<!-- Base colors (background) -->
<div class="bg-base-100">Base 100 (main bg)</div>
<div class="bg-base-200">Base 200 (slightly darker)</div>
<div class="bg-base-300">Base 300 (darker)</div>
<div class="text-base-content">Base content (text color)</div>

<!-- State colors -->
<div class="bg-info text-info-content">Info</div>
<div class="bg-success text-success-content">Success</div>
<div class="bg-warning text-warning-content">Warning</div>
<div class="bg-error text-error-content">Error</div>

Framework integration

React / Next.js

TScomponents/Button.tsx
TypeScript
// components/Button.tsx
interface ButtonProps {
  variant?: 'primary' | 'secondary' | 'accent' | 'ghost'
  size?: 'lg' | 'md' | 'sm' | 'xs'
  children: React.ReactNode
  onClick?: () => void
  loading?: boolean
  disabled?: boolean
}

export function Button({
  variant = 'primary',
  size = 'md',
  children,
  onClick,
  loading = false,
  disabled = false,
}: ButtonProps) {
  return (
    <button
      className={`btn btn-${variant} btn-${size} ${loading ? 'loading' : ''}`}
      onClick={onClick}
      disabled={disabled || loading}
    >
      {children}
    </button>
  )
}

// Usage
<Button variant="primary" size="lg" onClick={() => alert('Clicked!')}>
  Click me
</Button>
TScomponents/Card.tsx
TypeScript
// components/Card.tsx
interface CardProps {
  title: string
  description?: string
  image?: string
  actions?: React.ReactNode
  compact?: boolean
}

export function Card({ title, description, image, actions, compact = false }: CardProps) {
  return (
    <div className={`card bg-base-100 shadow-xl ${compact ? 'card-compact' : ''}`}>
      {image && (
        <figure>
          <img src={image} alt={title} />
        </figure>
      )}
      <div className="card-body">
        <h2 className="card-title">{title}</h2>
        {description && <p>{description}</p>}
        {actions && <div className="card-actions justify-end">{actions}</div>}
      </div>
    </div>
  )
}

// Usage
<Card
  title="Product"
  description="Product description"
  image="/product.jpg"
  actions={<Button variant="primary">Buy</Button>}
/>
TScomponents/Modal.tsx
TypeScript
// components/Modal.tsx
import { useRef, useEffect } from 'react'

interface ModalProps {
  isOpen: boolean
  onClose: () => void
  title: string
  children: React.ReactNode
  actions?: React.ReactNode
}

export function Modal({ isOpen, onClose, title, children, actions }: ModalProps) {
  const dialogRef = useRef<HTMLDialogElement>(null)

  useEffect(() => {
    if (isOpen) {
      dialogRef.current?.showModal()
    } else {
      dialogRef.current?.close()
    }
  }, [isOpen])

  return (
    <dialog ref={dialogRef} className="modal" onClose={onClose}>
      <div className="modal-box">
        <button
          className="btn btn-sm btn-circle btn-ghost absolute right-2 top-2"
          onClick={onClose}
        >
        </button>
        <h3 className="font-bold text-lg">{title}</h3>
        <div className="py-4">{children}</div>
        {actions && <div className="modal-action">{actions}</div>}
      </div>
      <form method="dialog" className="modal-backdrop">
        <button onClick={onClose}>close</button>
      </form>
    </dialog>
  )
}

Vue 3

components/Button.vue
VUE
<!-- components/Button.vue -->
<script setup lang="ts">
interface Props {
  variant?: 'primary' | 'secondary' | 'accent' | 'ghost'
  size?: 'lg' | 'md' | 'sm' | 'xs'
  loading?: boolean
  disabled?: boolean
}

const props = withDefaults(defineProps<Props>(), {
  variant: 'primary',
  size: 'md',
  loading: false,
  disabled: false,
})

const emit = defineEmits(['click'])
</script>

<template>
  <button
    :class="[
      'btn',
      `btn-${variant}`,
      `btn-${size}`,
      { loading: loading }
    ]"
    :disabled="disabled || loading"
    @click="emit('click')"
  >
    <slot />
  </button>
</template>
components/ThemeSwitcher.vue
VUE
<!-- components/ThemeSwitcher.vue -->
<script setup lang="ts">
import { ref, onMounted, watch } from 'vue'

const themes = ['light', 'dark', 'cupcake', 'cyberpunk', 'synthwave']
const currentTheme = ref('light')

onMounted(() => {
  const saved = localStorage.getItem('theme')
  if (saved) {
    currentTheme.value = saved
    document.documentElement.setAttribute('data-theme', saved)
  }
})

watch(currentTheme, (newTheme) => {
  document.documentElement.setAttribute('data-theme', newTheme)
  localStorage.setItem('theme', newTheme)
})
</script>

<template>
  <select v-model="currentTheme" class="select select-bordered">
    <option v-for="theme in themes" :key="theme" :value="theme">
      {{ theme }}
    </option>
  </select>
</template>

Svelte

Button.svelte
SVELTE
<!-- Button.svelte -->
<script lang="ts">
  export let variant: 'primary' | 'secondary' | 'accent' | 'ghost' = 'primary'
  export let size: 'lg' | 'md' | 'sm' | 'xs' = 'md'
  export let loading = false
  export let disabled = false
</script>

<button
  class="btn btn-{variant} btn-{size}"
  class:loading
  disabled={disabled || loading}
  on:click
>
  <slot />
</button>
ThemeSwitcher.svelte
SVELTE
<!-- ThemeSwitcher.svelte -->
<script lang="ts">
  import { onMount } from 'svelte'

  const themes = ['light', 'dark', 'cupcake', 'cyberpunk', 'synthwave']
  let currentTheme = 'light'

  onMount(() => {
    const saved = localStorage.getItem('theme')
    if (saved) {
      currentTheme = saved
      document.documentElement.setAttribute('data-theme', saved)
    }
  })

  function handleChange(event: Event) {
    const target = event.target as HTMLSelectElement
    currentTheme = target.value
    document.documentElement.setAttribute('data-theme', currentTheme)
    localStorage.setItem('theme', currentTheme)
  }
</script>

<select class="select select-bordered" value={currentTheme} on:change={handleChange}>
  {#each themes as theme}
    <option value={theme}>{theme}</option>
  {/each}
</select>

Responsiveness

Breakpoints with Tailwind

Code
HTML
<!-- Responsive cards -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
  <div class="card bg-base-100 shadow-xl">
    <div class="card-body">
      <h2 class="card-title">Card 1</h2>
    </div>
  </div>
  <div class="card bg-base-100 shadow-xl">
    <div class="card-body">
      <h2 class="card-title">Card 2</h2>
    </div>
  </div>
  <div class="card bg-base-100 shadow-xl">
    <div class="card-body">
      <h2 class="card-title">Card 3</h2>
    </div>
  </div>
</div>

<!-- Responsive buttons -->
<button class="btn btn-sm md:btn-md lg:btn-lg">
  Responsive button
</button>

<!-- Responsive drawer -->
<div class="drawer lg:drawer-open">
  <input id="my-drawer" type="checkbox" class="drawer-toggle" />
  <div class="drawer-content">
    <!-- Page content -->
    <label for="my-drawer" class="btn btn-primary drawer-button lg:hidden">
      Open drawer
    </label>
  </div>
  <div class="drawer-side">
    <label for="my-drawer" aria-label="close sidebar" class="drawer-overlay"></label>
    <ul class="menu p-4 w-80 min-h-full bg-base-200">
      <li><a>Sidebar Item 1</a></li>
      <li><a>Sidebar Item 2</a></li>
    </ul>
  </div>
</div>

Accessibility

ARIA attributes

Code
HTML
<!-- Button with ARIA -->
<button class="btn btn-primary" aria-label="Save document">
  <svg>...</svg>
  Save
</button>

<!-- Modal with ARIA -->
<dialog id="modal" class="modal" aria-labelledby="modal-title" aria-describedby="modal-desc">
  <div class="modal-box">
    <h3 id="modal-title" class="font-bold text-lg">Title</h3>
    <p id="modal-desc" class="py-4">Modal description</p>
  </div>
</dialog>

<!-- Tabs with roles -->
<div role="tablist" class="tabs tabs-boxed" aria-label="Navigation tabs">
  <button role="tab" class="tab" aria-selected="false">Tab 1</button>
  <button role="tab" class="tab tab-active" aria-selected="true">Tab 2</button>
  <button role="tab" class="tab" aria-selected="false">Tab 3</button>
</div>

<!-- Alert with role -->
<div role="alert" class="alert alert-warning">
  <span>Warning: Check your data</span>
</div>

<!-- Progress with ARIA -->
<progress
  class="progress progress-primary w-56"
  value="70"
  max="100"
  aria-label="Loading progress"
  aria-valuenow="70"
  aria-valuemin="0"
  aria-valuemax="100"
></progress>

Focus and keyboard navigation

Code
HTML
<!-- Skip link -->
<a href="#main-content" class="btn btn-link sr-only focus:not-sr-only">
  Skip to main content
</a>

<!-- Focus ring -->
<button class="btn btn-primary focus:ring focus:ring-primary focus:ring-offset-2">
  Visible focus
</button>

<!-- Focusable card -->
<div class="card bg-base-100 shadow-xl" tabindex="0" role="article">
  <div class="card-body">
    <h2 class="card-title">Focusable Card</h2>
    <p>Can be navigated with Tab key</p>
  </div>
</div>

Performance optimization

Purging unused classes

JStailwind.config.js
JavaScript
// tailwind.config.js
module.exports = {
  content: [
    "./src/**/*.{js,ts,jsx,tsx,html}",
  ],
  theme: {
    extend: {},
  },
  plugins: [require("daisyui")],
  daisyui: {
    themes: ["light", "dark"], // Only used themes
    styled: true,
    base: true,
    utils: true,
    logs: false, // Disable logs in production
  },
}

Lazy loading components

Code
TypeScript
// React - dynamic modal import
import dynamic from 'next/dynamic'

const Modal = dynamic(() => import('./Modal'), {
  loading: () => <span className="loading loading-spinner" />,
  ssr: false
})

CSS minification

Code
Bash
# Build with minification
NODE_ENV=production npx tailwindcss -i ./src/input.css -o ./dist/output.css --minify

Best practices

Project structure

Code
TEXT
src/
├── components/
│   ├── ui/           # Base DaisyUI components
│   │   ├── Button.tsx
│   │   ├── Card.tsx
│   │   ├── Modal.tsx
│   │   └── Input.tsx
│   ├── layout/       # Layouts
│   │   ├── Navbar.tsx
│   │   ├── Sidebar.tsx
│   │   └── Footer.tsx
│   └── features/     # Business components
├── styles/
│   └── globals.css   # Tailwind import
└── lib/
    └── theme.ts      # Theme configuration

Consistency in your project

TSlib/theme.ts
TypeScript
// lib/theme.ts - Centralizing colors and variants
export const buttonVariants = {
  primary: 'btn-primary',
  secondary: 'btn-secondary',
  danger: 'btn-error',
  success: 'btn-success',
} as const

export const sizeVariants = {
  small: 'btn-sm',
  medium: 'btn-md',
  large: 'btn-lg',
} as const

// Usage
<button className={`btn ${buttonVariants.primary} ${sizeVariants.medium}`}>
  Button
</button>

Combining with Tailwind utilities

Code
HTML
<!-- DaisyUI + Tailwind utilities -->
<button class="btn btn-primary hover:scale-105 transition-transform">
  Animated button
</button>

<div class="card bg-base-100 shadow-xl hover:shadow-2xl transition-shadow">
  <div class="card-body">
    <h2 class="card-title text-gradient">Gradient title</h2>
  </div>
</div>

<input
  class="input input-bordered focus:input-primary w-full"
  placeholder="Focus changes the color"
/>

FAQ - Frequently asked questions

Does DaisyUI increase bundle size?

Not significantly. DaisyUI is pure CSS that gets purged by Tailwind in production. The components you use add minimal overhead. In practice it often reduces the bundle, because you use shorter classes (btn instead of 10 utility classes).

Can I use DaisyUI with JavaScript components?

Yes! DaisyUI is CSS only - it does not require any JavaScript. You can add your own logic or use libraries like Headless UI for more complex interactions (dropdown, modal with focus trap, etc.).

How do I customize existing components?

You have three options:

  1. Add Tailwind classes alongside DaisyUI classes
  2. Create a custom theme with custom colors
  3. Override styles in CSS using selectors

Is DaisyUI compatible with Tailwind v4?

Yes! DaisyUI supports Tailwind v4. Check the documentation for configuration details.

How do I implement dark mode?

DaisyUI has built-in support through themes. Set data-theme="dark" on <html> and use the "dark" theme or any other dark theme such as "dracula", "night", "forest".

Summary

DaisyUI is the ideal solution for projects using Tailwind CSS, offering:

  • Semantic classes - More readable code, faster writing
  • 35+ themes - Easy appearance change for your entire application
  • 50+ components - Everything you need for UI
  • Zero JavaScript - Works with any framework
  • Full compatibility - With Tailwind utilities and responsive design
  • 100% free - Open source, MIT License

If you use Tailwind CSS and want to speed up development without sacrificing flexibility, DaisyUI is an excellent choice.