shadcn/ui のインストールとテーマカスタマイズ完全ガイド(CSS 変数つき)
shadcn/ui を初めて使ったとき、「npm パッケージではない」という設定に面食らいました。コードをプロジェクトにコピーする?さすがに原始的すぎるのでは、と思ったのです。
ところが何度か使ううちに、そここそが shadcn/ui の強みだと気づきました。すべてのコンポーネントのソースを自分が持っているので、好きなように書き換えられます。バージョン競合に悩む必要もなく、コンポーネントライブラリのデザインに縛られることもありません。
今日は、shadcn/ui のインストール設定とテーマカスタマイズについて話していきます。とくに CSS 変数を使って、ブランド化されたデザインシステムをどう実現するかが中心です。読み終わるころには、5 分で基本設定を済ませ、あとは 1 時間ほどでテーマを自分好みに調整できるようになっているはずです。
一、クイックインストール:2 つの方法
方法その 1:CLI でワンコマンド初期化(おすすめ)
新規プロジェクトなら、このコマンドを使えば一発です。
npx shadcn@latest init
実行すると、いくつか質問されます。TypeScript と JavaScript のどちらを使うか?どのスタイルを選ぶか?デフォルトテーマは何にするか?すべて対話形式なので、案内に沿って選ぶだけで大丈夫です。
インストールが終わると、プロジェクトにいくつかファイルが追加されます。
components.json- 設定ファイルlib/utils.ts- ユーティリティ関数components/ui/- コンポーネントの保存ディレクトリ
コンポーネントを追加するのも簡単です。たとえばボタンが欲しいなら、こうします。
npx shadcn@latest add button
コンポーネントのコードが components/ui/button.tsx に自動でコピーされるので、そのまま import して使えます。
ここに落とし穴があります。プロジェクトがすでにある程度進んでいると、tailwind.config.js や globals.css に色々と書き込まれているかもしれません。shadcn の init コマンドはこれらのファイルを上書きするので、プロジェクトの立ち上げ時に入れておくのが一番です。
あるブロガーがうまいことを言っていました。shadcn/ui はプロジェクトの「最初の依存関係の 1 つ」として入れておけ、あとから追加するな、と。痛い教訓ですね。
方法その 2:手動インストール(既存プロジェクト向け)
プロジェクトがすでに形になっていると、CLI で設定を上書きするリスクが大きすぎます。その場合は手動でインストールしましょう。
いくつかのステップに分けて進めます。
第一歩:Tailwind CSS が入っているか確認
shadcn のコンポーネントはすべて Tailwind で書かれているので、未導入なら先に Tailwind を入れます。これは詳しく説明しません。公式チュートリアルがわかりやすいです。
第二歩:依存関係をインストール
npm install class-variance-authority clsx tailwind-merge
npm install lucide-react
class-variance-authority(略して CVA)は便利なツールで、あとでコンポーネントのバリアントを作るときに使います。
第三歩:パスエイリアスを設定
tsconfig.json に次を追加します。
{
"compilerOptions": {
"paths": {
"@/*": ["./*"]
}
}
}
こうすれば @/components/ui/button のようにコンポーネントを読み込めるようになり、../../../ を延々と書かずに済みます。
第四歩:components.json を作成
プロジェクトのルートディレクトリに、このファイルを新規作成します。
{
"style": "new-york",
"rsc": true,
"tailwind": {
"config": "tailwind.config.ts",
"css": "app/globals.css",
"baseColor": "neutral",
"cssVariables": true
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils"
}
}
cssVariables: true の行が重要です。Tailwind の utility class ではなく、CSS 変数でテーマを作るという指定です。
第五歩:スタイルを追加
globals.css に shadcn の基本スタイルを追加します。これはあとのテーマの章で詳しく説明します。
二、テーマシステムを理解する:CSS 変数の使いこなし方
shadcn/ui のテーマシステムは、シンプルな約束ごとに基づいています。どの色にも background と foreground の 2 つの変数がある、というものです。
どういう意味でしょうか。例を挙げてみます。
:root {
--primary: 222.2 47.4% 11.2%;
--primary-foreground: 210 40% 98%;
}
--primary はボタンの背景色、--primary-foreground はボタン上の文字色です。このようにペアにしておく利点は、1 つの変数を変えるだけで、関連するすべてのコンポーネントが一緒に変わることです。
CSS 変数の一覧
shadcn/ui はデフォルトで次の変数を定義しています。
| 変数 | 用途 |
|---|---|
--background | ページの背景色 |
--foreground | ページの文字色 |
--card | カードの背景 |
--card-foreground | カードの文字 |
--popover | ポップオーバーの背景 |
--popover-foreground | ポップオーバーの文字 |
--primary | メインカラー(ボタン、リンク) |
--primary-foreground | メインカラー上の文字 |
--secondary | サブカラー |
--secondary-foreground | サブカラー上の文字 |
--muted | 控えめな背景 |
--muted-foreground | 控えめな文字 |
--accent | アクセントカラー |
--accent-foreground | アクセントカラー上の文字 |
--destructive | 危険な操作(削除ボタン) |
--destructive-foreground | 危険な操作上の文字 |
--border | ボーダー |
--input | 入力欄 |
--ring | フォーカスリング |
数は多く見えますが、background / foreground のパターンさえ理解すれば、覚えるのは簡単です。
HSL 形式の秘密
気づいたかもしれませんが、shadcn の色の値は標準的な HSL 形式ではありません。
/* ❌ 標準の HSL */
--primary: hsl(222.2, 47.4%, 11.2%);
/* ✅ shadcn の形式 */
--primary: 222.2 47.4% 11.2%;
なぜこの「裸」の形式で書くのでしょうか。
Tailwind が透明度修飾子に対応しているからです。たとえば bg-primary/50 は 50% の透明度のメインカラーを表します。変数が完全な hsl() 形式だと、この機能は使えません。
裸の形式にしておくと、Tailwind が自動的に hsl() と透明度を付けてくれます。よく考えられた設計です。
三、自分のブランドテーマをカスタマイズする
方法その 1:CSS 変数を直接書き換える
一番シンプルな方法です。globals.css を開いて :root の部分を探し、色の値を書き換えるだけです。
たとえばメインカラーをデフォルトの青から紫に変えたいなら、こうします。
:root {
--primary: 270 60% 60%;
--primary-foreground: 0 0% 100%;
}
.dark {
--primary: 270 60% 70%;
--primary-foreground: 0 0% 0%;
}
保存すれば、bg-primary を使っているボタンやリンクはすべて紫に変わります。
方法その 2:OKLCH カラースペースを使う(Tailwind v4)
Tailwind v4 を使っているなら、OKLCH カラースペースを検討してもよいでしょう。HSL に比べて、OKLCH は色の感じ方が人の目に近く、生成される色階調がより均一になります。
:root {
--primary: oklch(0.6 0.2 270);
--primary-foreground: oklch(0.98 0 0);
}
ここで oklch(0.6 0.2 270) の 3 つのパラメータは次の意味です。
0.6- 明度(0〜1)0.2- 彩度(0〜0.4 程度)270- 色相の角度(0〜360)
方法その 3:オンラインツールで生成
自分で色を組み合わせるのが面倒なら、オンラインツールが使えます。
おすすめはこちらです。Shadcn Theme Generator
メインカラーを 1 つ選べば、ツールがライトとダークの両方を含む完全な CSS 変数一式を自動生成してくれます。あとは globals.css にコピー&ペーストするだけです。
四、ダークモードの設定
next-themes でテーマ切り替えを実装
shadcn/ui 自体にはテーマ切り替え機能がありませんが、next-themes というライブラリで実現できます。
まずインストールします。
npm install next-themes
次に layout.tsx で設定します。
import { ThemeProvider } from "next-themes"
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="ja" suppressHydrationWarning>
<body>
<ThemeProvider
attribute="class"
defaultTheme="system"
enableSystem
>
{children}
</ThemeProvider>
</body>
</html>
)
}
いくつか重要なポイントがあります。
suppressHydrationWarningは必須です。付けないとハイドレーション警告が出ますattribute="class"は class 名でテーマを切り替えるという意味ですdefaultTheme="system"はデフォルトでシステムに追随するという意味ですenableSystemでシステムテーマの検出を有効にします
テーマ切り替えボタンを作る
useTheme フックで現在のテーマと切り替え関数を取得します。
import { useTheme } from "next-themes"
import { Moon, Sun } from "lucide-react"
export function ThemeToggle() {
const { theme, setTheme } = useTheme()
return (
<button
onClick={() => setTheme(theme === "dark" ? "light" : "dark")}
className="p-2 rounded-md hover:bg-accent"
>
{theme === "dark" ? <Sun size={20} /> : <Moon size={20} />}
</button>
)
}
デフォルトをダークモードにする
サイトをデフォルトでダークモードにしたいなら、2 つの方法があります。
方法その 1:dark class をハードコードする
<html lang="ja" className="dark">
こう書くと、テーマはダークに固定され、切り替えられなくなります。
方法その 2:デフォルトテーマを設定する
<ThemeProvider
attribute="class"
defaultTheme="dark" // デフォルトはダーク
enableSystem={false} // システム検出をオフ
>
これなら、ユーザーは手動で切り替えられますが、初期状態はダークになります。
五、上級カスタマイズ:コンポーネントのバリアント
CVA でカスタムバリアントを作る
ボタンにいくつかのスタイル、たとえば「危険」「成功」「グラデーション」を追加したいときがあります。CVA を使えば、こうしたバリアントを手軽に定義できます。
import { cva, type VariantProps } from "class-variance-authority"
const buttonVariants = cva(
"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors",
{
variants: {
variant: {
default: "bg-primary text-primary-foreground hover:bg-primary/90",
destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline",
},
size: {
default: "h-10 px-4 py-2",
sm: "h-9 rounded-md px-3",
lg: "h-11 rounded-md px-8",
icon: "h-10 w-10",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
}
)
export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {}
そしてコンポーネントの中で使います。
<button className={buttonVariants({ variant: "destructive", size: "lg" })}>
削除
</button>
shadcn コンポーネントのソースを直接書き換えない
これはベストプラクティスの問題です。
shadcn のコンポーネントコードは自分のプロジェクトの中にあるので、好きなように書き換えられます。とはいえ、元のファイルを直接いじるのではなく、ラッパーコンポーネントを作ることをおすすめします。
なぜでしょうか。shadcn はコンポーネントを頻繁に更新するため、元のファイルを書き換えていると、更新のときに手動でマージする必要があり、とても面倒だからです。
より良いやり方はこちらです。
// components/brand-button.tsx
import { Button } from "@/components/ui/button"
import { cva } from "class-variance-authority"
const brandButtonVariants = cva("...", {
variants: {
brand: {
primary: "bg-brand-primary text-white",
secondary: "bg-brand-secondary text-black",
},
},
})
export function BrandButton({ brand, ...props }) {
return <Button className={brandButtonVariants({ brand })} {...props} />
}
こうすれば元の Button コンポーネントはそのまま保たれ、自分専用の BrandButton を作れます。今後 shadcn が更新されても、自分のカスタマイズには影響しません。
六、よくある問題とハマりどころ
問題その 1:インストール後にスタイルが効かない
次の点を確認しましょう。
globals.cssはlayout.tsxで import されているか?- Tailwind の
content設定にcomponents/**/*が含まれているか? components.jsonのパス設定は正しいか?
問題その 2:テーマ切り替え時にちらつく
これはたいていハイドレーションの不一致が原因です。次を確認しましょう。
<html>タグにsuppressHydrationWarningを付けたか- ThemeProvider がアプリ全体を包んでいるか
- サーバーサイドレンダリング時に theme を読み取っていないか(undefined になります)
問題その 3:CSS 変数が効かない
考えられる原因はこちらです。
- 変数名が間違っている(
--primaryForegroundではなく--primary-foregroundに注意) - 対応する
.darkのスタイルがない - 変数の値の形式が間違っている(裸の HSL か OKLCH を使う)
問題その 4:コンポーネントのスタイルが競合する
プロジェクトにすでにスタイルシステムがあると、shadcn のものと競合する場合があります。解決策はこちらです。
- shadcn コンポーネントに namespace を付ける(例:
shadcn-button) - Tailwind の layer の優先度を調整する
- CVA で自分のバリアントを作り、デフォルトスタイルに依存しない
七、まとめ
shadcn/ui のインストール設定は、実はかなりシンプルです。鍵になるのは「依存パッケージではなくコードをコピーする」という設計思想を理解することです。これによって完全にコントロールできる一方、プロジェクトごとにコンポーネントのコードを自分で管理する必要があります。
テーマカスタマイズの面では、CSS 変数システムがとてもエレガントに設計されています。いくつかの変数の値を変えるだけで、アプリ全体の配色が一緒に変わります。next-themes と組み合わせれば、ライトとダークの切り替えも数行のコードで済みます。
最後にいくつかのアドバイスです。
- 新規プロジェクトはまず CLI で初期化して、手動設定の手間を省く
- 意味のある色変数を使う。具体的な色名ではなく primary や secondary を使う
- ライトとダークの両方でコントラストをテストして、読みやすさを確保する
- ソースを書き換えずラッパーコンポーネントを作る。あとから更新しやすい
次にテーマ付きの UI を素早く組み立てたくなったら、shadcn/ui を試してみてください。コピー&ペーストの快適さは、使った人にしかわかりません。
参考資料
- shadcn/ui 公式ドキュメント - Installation
- shadcn/ui 公式ドキュメント - Theming
- shadcn/ui 公式ドキュメント - Dark Mode
- Generate Custom shadcn/ui Themes
- Theming in shadcn UI: CSS Variables
shadcn/ui のインストールとテーマカスタマイズ
ゼロから shadcn/ui をインストールし、テーマシステムを設定して、ブランド化デザインを実現する
⏱️ 目安時間: 30 分
- 1
ステップ1: CLI でのクイック初期化
新しいプロジェクトでインストールコマンドを実行します。
• npx shadcn@latest init
• TypeScript / New York スタイル / デフォルトテーマを選択
• CLI の設定完了を待つ - 2
ステップ2: ブランドのメインカラーを変更
globals.css の CSS 変数を編集します。
• app/globals.css を開く
• :root にある --primary 変数を探す
• 自分のブランドカラーに書き換える(HSL または OKLCH 形式)
• コントラストを確保するため --primary-foreground も同時に変更 - 3
ステップ3: ダークモードを設定
next-themes をインストールして設定します。
• npm install next-themes
• layout.tsx に ThemeProvider を追加
• ハイドレーション警告を防ぐため suppressHydrationWarning を設定
• テーマ切り替えコンポーネントを作成 - 4
ステップ4: コンポーネントのバリアントを作成
CVA でカスタムスタイルを定義します。
• class-variance-authority をインストール
• variants と defaultVariants を定義
• コンポーネントで buttonVariants() を適用
• 元の shadcn コンポーネントはそのまま保つ
FAQ
shadcn/ui と従来の UI コンポーネントライブラリは何が違うの?
なぜ新規プロジェクトの初期化時に shadcn/ui を入れることを勧めるの?
CSS 変数はなぜ標準の HSL ではなく「裸」の形式で書くの?
ブランドのメインカラーはどう変更すればいい?
ダークモードでちらつきが起きるのはなぜ?
shadcn コンポーネントのソースを直接書き換えてもいい?
4分で読めます · 公開日: 2026年3月26日 · 更新日: 2026年6月8日
Tailwind と shadcn/ui 実践ガイド
検索からこのページに来た場合は、前後の記事もあわせて読むと同じテーマの理解がかなり早く深まります。
前の記事
Tailwind v4 + Vite:5 分で完成する設定テンプレートとディレクトリ構成
Tailwind CSS v4 + Vite プロジェクトをゼロから設定する方法を解説。5 分で使える完全テンプレートと推奨ディレクトリ構成、さらに v3 から v4 への移行チェックリストで、モダンなフロントエンド環境をすばやく構築できます。
第 1 / 11 記事
次の記事
shadcn/ui で管理画面の骨組みを構築:Sidebar + Layout ベストプラクティス
shadcn/ui Sidebar と Next.js Layout を統合するベストプラクティスを習得しましょう。コンポーネント設計からレスポンシブ対応、権限制御まで、拡張しやすい管理画面の骨組みを手を動かしながら構築します。完全なコード例つき
第 3 / 11 記事
関連記事
Tailwind レスポンシブレイアウト実践:コンテナクエリとブレークポイント戦略
Tailwind レスポンシブレイアウト実践:コンテナクエリとブレークポイント戦略
Tailwind ダークモード:class と data-theme の2つの方式を比較
Tailwind ダークモード:class と data-theme の2つの方式を比較
shadcn/ui コンポーネント組み合わせパターン:実践ベストプラクティス
コメント
GitHubアカウントでログインしてコメントできます