はじめに
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は、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")],
}
これだけで完了。設定ファイルをいじる必要がほとんどないのは時短になります。
基本的な使い方
ボタン
<!-- 基本のボタン -->
<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 />
実践的なユースケース
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だけで動くのか」と驚くと思いますよ。