はじめに
Tailwind CSSを使っていると、こんな経験ありませんか。
「flex items-center justify-between gap-4 px-6 py-3 bg-blue-500 hover:bg-blue-600 text-white font-medium rounded-lg shadow-md transition-colors duration-200...これ、ただのボタンなんだけど」
個人的には、Tailwind CSSの自由度は素晴らしいと思います。でも正直なところ、同じようなクラスの組み合わせを何度も書くのは疲れる。
そこで出会ったのがdaisyUI。GitHubで39,500スター以上、月間210万ダウンロードという化け物級の人気ライブラリです。
使ってみて「あ、これだよこれ」となったので、今回はその魅力を紹介します。
とはいえ、説明を読むよりクラスを当てて動かした方が早いと思います。ボタンのバリアント切り替え、バッジ・アラートの状態表示、モーダルとドロワーの開閉、テーマ切り替えまで、daisyUIのクラスだけで動くサンプルをブラウザ上にいくつか用意したので、先に触ってみたい方はこちらからどうぞ。
daisyUIとは
daisyUIは、Tailwind CSS用のコンポーネントライブラリです。でも普通のUIライブラリとはちょっと違う。
セマンティックなクラス名でUIコンポーネントを使えるようにしてくれるんですよ。
たとえば、さっきの長いボタンのクラス名。daisyUIなら:
<button class="btn btn-primary">ボタン</button>
これだけ。公式サイトによると「88%少ないクラス名」「79%小さいDOM」で同じUIが作れるとのこと。
最新バージョンはv5.5.8。5年以上の開発実績があり、298人以上のコントリビューターが参加しています。MITライセンスなので、商用プロジェクトでも安心して使えます。
特徴・メリット
1. ピュアCSSでJavaScript不要
これ、意外と重要なポイント。daisyUIはピュアCSSで動作するので、React、Vue、Svelte、Next.js、Laravel、Rails...どんなフレームワークでも使えます。
JavaScriptの依存がないから、バンドルサイズを気にする必要もない。フレームワークを乗り換えても、UIの知識がそのまま使える。コスパ的にかなり優秀です。
2. 35以上のテーマが使える
個人的には、これが一番刺さった機能。
ライトモード、ダークモード、カスタムテーマ...全部CSSカスタムプロパティで管理されていて、切り替えが一瞬。
<!-- これだけでテーマ切り替え -->
<html data-theme="dark">
テーマはlight、dark、cupcake、retro、cyberpunkなど35種類以上。自分でカスタムテーマを作ることもできます。
30代になって思うのは、ダークモード対応は今や必須だということ。daisyUIなら最初から入っているので、後から対応する手間が省けます。
3. 65以上のコンポーネント
実務で必要になるUIパーツは、ほぼ揃っています:
- Actions: Button、Dropdown、Modal、Swap
- Data display: Card、Avatar、Badge、Carousel、Table
- Navigation: Navbar、Breadcrumbs、Pagination、Menu
- Data input: Input、Select、Checkbox、Radio、Toggle
- Feedback: Alert、Toast、Loading、Progress
- Layout: Drawer、Footer、Hero
- Mockup: Browser、Phone、Code Window
特にMockupコンポーネントは面白い。ブラウザやスマホのモックアップが簡単に作れるので、ポートフォリオやLPで重宝します。
4. Tailwind CSSとの完璧な共存
daisyUIはTailwind CSSを置き換えるものではなく、拡張するもの。
<!-- daisyUIのクラスとTailwindのユーティリティを併用 -->
<button class="btn btn-primary w-full mt-4 uppercase tracking-wide">
送信する
</button>
既存のTailwindプロジェクトに導入しても、何も壊れない。これ、移行のハードルを大幅に下げてくれます。
インストール方法
npm/yarn/pnpmでインストール
# npm
npm i -D daisyui@latest
# yarn
yarn add -D daisyui@latest
# pnpm
pnpm add -D daisyui@latest
CSSに追加
Tailwind CSS v4の場合:
/* globals.css */
@import "tailwindcss";
@plugin "daisyui";
Tailwind CSS v3の場合はtailwind.config.jsに追加:
// tailwind.config.js
module.exports = {
plugins: [require("daisyui")],
}
これだけで完了。設定ファイルをいじる必要がほとんどないのは時短になります。
daisyUIのサンプルを動かす
ここではビルド不要で試せるように、daisyUIの配布CSS(daisyui@5.7.16)とTailwind CSSのブラウザ版(@tailwindcss/browser@4.3.3)をCDNから読み込む形でサンプルを組んでいます。下のセレクトボックスでクラス名を切り替えると、btn要素の見た目とバッジに表示されるクラス文字列がその場で変わります。btn-outline btn-primaryのように、daisyUIのクラスは複数組み合わせて使えることも確認できます。
要点だけ抜き出すと、こんな見た目です。
<select id="variant">
<option value="btn-primary">btn-primary</option>
<option value="btn-outline btn-primary">btn-outline btn-primary</option>
<option value="btn-ghost">btn-ghost</option>
</select>
<button id="sample-btn" class="btn btn-primary">サンプルボタン</button>
<script>
select.addEventListener('change', () => {
// btnクラスに選んだバリアントを足すだけで見た目が切り替わる
btn.className = `btn ${select.value}`
})
</script>
実際に動かせるのが下のサンプルです。セレクトボックスの値を変えると即座にボタンの色・形が変わります。
セレクトボックスのchangeイベントでbutton.classNameを書き換えているだけです。実務ではbtn-primaryをbtn-errorに変えれば削除ボタンのような危険操作用の見た目に、btn-lgやbtn-smを足せばサイズ違いのボタンに、といった具合にクラス名の組み合わせだけでバリエーションを作れます。試しにoptionの値をbtn-circle btn-primaryなどに書き換えて、挙動を確認してみてください。
基本的な使い方
ボタン
<!-- 基本のボタン -->
<button class="btn">Button</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-lg">Large</button>
<button class="btn btn-sm">Small</button>
<button class="btn btn-xs">Tiny</button>
<!-- スタイル -->
<button class="btn btn-outline btn-primary">Outline</button>
<button class="btn btn-ghost">Ghost</button>
<button class="btn btn-link">Link</button>
<!-- 状態 -->
<button class="btn btn-primary loading">Loading</button>
<button class="btn btn-disabled">Disabled</button>
カード
<div class="card w-96 bg-base-100 shadow-xl">
<figure>
<img src="/image.jpg" alt="Image" />
</figure>
<div class="card-body">
<h2 class="card-title">カードタイトル</h2>
<p>カードの説明文がここに入ります。</p>
<div class="card-actions justify-end">
<button class="btn btn-primary">詳細を見る</button>
</div>
</div>
</div>
モーダル
<!-- トリガーボタン -->
<button class="btn" onclick="my_modal.showModal()">
モーダルを開く
</button>
<!-- モーダル本体 -->
<dialog id="my_modal" class="modal">
<div class="modal-box">
<h3 class="font-bold text-lg">確認</h3>
<p class="py-4">この操作を実行してもよろしいですか?</p>
<div class="modal-action">
<form method="dialog">
<button class="btn btn-ghost">キャンセル</button>
<button class="btn btn-primary">確認</button>
</form>
</div>
</div>
</dialog>
フォーム要素
<!-- テキスト入力 -->
<input type="text" placeholder="メールアドレス" class="input input-bordered w-full max-w-xs" />
<!-- セレクト -->
<select class="select select-bordered w-full max-w-xs">
<option disabled selected>選択してください</option>
<option>オプション1</option>
<option>オプション2</option>
</select>
<!-- チェックボックス -->
<input type="checkbox" class="checkbox checkbox-primary" checked />
<!-- トグル -->
<input type="checkbox" class="toggle toggle-primary" checked />
実践的なユースケース
daisyUIのバッジ・アラートで状態を出し分ける
フォームの処理結果やAPIレスポンスの状態を表示するとき、daisyUIならbadge-{状態}・alert-{状態}のようにクラス名の末尾を変えるだけで、info・success・warning・errorの4色に切り替えられます。色ごとにCSSを書く必要がありません。
<span id="badge" class="badge badge-success">success</span>
<div id="alert" role="alert" class="alert alert-success">
<span>処理が完了しました。</span>
</div>
<script>
select.addEventListener('change', () => {
const status = select.value
badge.className = `badge badge-${status}`
alertBox.className = `alert alert-${status}`
})
</script>
下のサンプルではセレクトボックスでステータスを切り替えると、バッジとアラートの色・文言が連動して変わります。
badge-warningやalert-errorのように、クラス名の一部を差し替えるだけで色とニュアンスが変わることが分かります。フォームのバリデーション結果やトースト通知など、状態によって見た目を出し分けたい場面でそのまま応用できます。
daisyUIのモーダルとドロワーを操作する
daisyUIのモーダルは素のHTMLの<dialog>要素とshowModal() / close()をそのまま使います。ドロワー(サイドメニュー)はJavaScript不要で、drawer-toggleというcheckboxとdrawer-side要素の組み合わせだけで開閉できるのが特徴です。
<div class="drawer">
<input id="my-drawer" type="checkbox" class="drawer-toggle" />
<div class="drawer-content">
<label for="my-drawer" class="btn btn-primary">ドロワーを開く</label>
</div>
<div class="drawer-side">
<label for="my-drawer" class="drawer-overlay"></label>
<ul class="menu bg-base-200 min-h-full w-60 p-4">
<li><a>メニュー1</a></li>
</ul>
</div>
</div>
<dialog id="my_modal" class="modal">
<div class="modal-box">
<form method="dialog">
<button class="btn">閉じる</button>
</form>
</div>
</dialog>
実際に開閉できるサンプルが下です。「ドロワーを開く」ボタンはチェックボックスのラベル経由で、「モーダルを開く」ボタンはonclickでshowModal()を呼んでいます。
ドロワーがcheckboxの状態だけで開閉できているのがポイントです。JavaScriptを1行も書かずに、CSSの隣接セレクタだけでサイドメニューの表示・非表示を切り替えています。一方モーダルは<dialog>のネイティブAPIなので、my_modal.close()を別のボタンに割り当てれば任意のタイミングで閉じる処理も追加できます。
daisyUIのテーマ切り替え(data-theme)を試す
daisyUIの目玉機能の一つが35種類以上のテーマです。切り替え自体はシンプルで、<html>要素のdata-theme属性を書き換えるだけで、ページ全体の配色が一括で変わります。デフォルトのlight・dark以外のテーマを使う場合は、daisyui@5.7.16/themes.cssも追加で読み込みます。
<html data-theme="light">
...
</html>
<script>
select.addEventListener('change', () => {
document.documentElement.setAttribute('data-theme', select.value)
})
</script>
下のセレクトボックスでテーマ名を選ぶと、カード・ボタン・バッジの配色がまとめて切り替わります。
cyberpunkやsynthwaveを選ぶと分かりやすいですが、背景色・文字色・プライマリカラーがテーマごとにまったく違う印象になります。CSSカスタムプロパティで管理されているぶん、独自のブランドカラーに合わせたカスタムテーマも同じ仕組みで追加できます。
Reactでの使用例
// components/ContactForm.tsx
export function ContactForm() {
return (
<div className="card bg-base-100 shadow-xl max-w-md mx-auto">
<div className="card-body">
<h2 className="card-title">お問い合わせ</h2>
<div className="form-control">
<label className="label">
<span className="label-text">お名前</span>
</label>
<input
type="text"
placeholder="山田太郎"
className="input input-bordered"
/>
</div>
<div className="form-control">
<label className="label">
<span className="label-text">メールアドレス</span>
</label>
<input
type="email"
placeholder="email@example.com"
className="input input-bordered"
/>
</div>
<div className="form-control">
<label className="label">
<span className="label-text">メッセージ</span>
</label>
<textarea
className="textarea textarea-bordered h-24"
placeholder="お問い合わせ内容"
></textarea>
</div>
<div className="form-control mt-4">
<button className="btn btn-primary">送信する</button>
</div>
</div>
</div>
)
}
テーマ切り替えの実装
// components/ThemeController.tsx
"use client"
import { useEffect, useState } from "react"
const themes = ["light", "dark", "cupcake", "retro", "cyberpunk"]
export function ThemeController() {
const [theme, setTheme] = useState("light")
useEffect(() => {
document.documentElement.setAttribute("data-theme", theme)
}, [theme])
return (
<div className="dropdown dropdown-end">
<div tabIndex={0} role="button" className="btn m-1">
テーマ
<svg className="w-4 h-4 fill-current" viewBox="0 0 20 20">
<path d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" />
</svg>
</div>
<ul tabIndex={0} className="dropdown-content z-[1] menu p-2 shadow bg-base-100 rounded-box w-52">
{themes.map((t) => (
<li key={t}>
<a onClick={() => setTheme(t)} className={theme === t ? "active" : ""}>
{t}
</a>
</li>
))}
</ul>
</div>
)
}
レスポンシブなナビゲーション
<div class="navbar bg-base-100 shadow-lg">
<div class="navbar-start">
<!-- モバイルメニュー -->
<div class="dropdown">
<div tabindex="0" role="button" class="btn btn-ghost lg:hidden">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h8m-8 6h16" />
</svg>
</div>
<ul tabindex="0" class="menu menu-sm dropdown-content mt-3 z-[1] p-2 shadow bg-base-100 rounded-box w-52">
<li><a>ホーム</a></li>
<li><a>サービス</a></li>
<li><a>会社概要</a></li>
<li><a>お問い合わせ</a></li>
</ul>
</div>
<a class="btn btn-ghost text-xl">MyApp</a>
</div>
<!-- デスクトップメニュー -->
<div class="navbar-center hidden lg:flex">
<ul class="menu menu-horizontal px-1">
<li><a>ホーム</a></li>
<li><a>サービス</a></li>
<li><a>会社概要</a></li>
<li><a>お問い合わせ</a></li>
</ul>
</div>
<div class="navbar-end">
<a class="btn btn-primary">無料で始める</a>
</div>
</div>
shadcn/uiとの比較
正直なところ、どちらも優秀なライブラリです。でも思想が違う。
| 項目 | daisyUI | shadcn/ui |
|---|---|---|
| アプローチ | CSSクラスを追加 | コードをコピー |
| JavaScript | 不要(ピュアCSS) | React依存 |
| カスタマイズ | テーマ+Tailwind | ソースを直接編集 |
| フレームワーク | どれでもOK | React系のみ |
| 学習コスト | 低い | やや高い |
| バンドルサイズ | 軽い | 使うものだけ |
個人的には、「React以外も使う」「素早くプロトタイプを作りたい」ならdaisyUI、「Reactに集中」「細かくカスタマイズしたい」ならshadcn/uiという使い分けがいいと思います。
両方使うこともできますが、デザインの一貫性を保つのが難しくなるので、プロジェクト開始時にどちらかに決めた方がいいですね。
まとめ
daisyUIを使い始めて感じた変化:
- コード量: クラス名が劇的に減った
- 開発速度: UIの実装が圧倒的に速くなった
- デザイン: 一貫性のある美しいUIが簡単に作れる
- テーマ対応: ダークモードが一瞬で実装できる
- 学習コスト: ほぼゼロ。ドキュメント見ながらすぐ使える
30代になって思うのは、効率的に美しいものを作れるツールこそ価値があるということ。daisyUIは、Tailwind CSSの自由度を残しつつ、面倒な部分を肩代わりしてくれる。
特に「Tailwind CSSは好きだけど、クラス名の羅列は疲れる」という人には刺さるはず。まだ試していない人は、公式サイトのコンポーネント一覧を見てみてください。「これ全部CSSだけで動くのか」と驚くと思いますよ。