shadcn/ui インストールとテーマカスタマイズ完全ガイド(CSS変数付き)
正直なところ、shadcn/uiを初めて使った時、「npmパッケージじゃない」という仕組みに戸惑いました。コードをプロジェクトにコピーする?原始的すぎると思いました。
でも何度か使ってみると、これこそが強みだと気づきました。全コンポーネントのソースコードを所有でき、自由に変更でき、バージョン競合もなく、コンポーネントライブラリの設計に縛られることもありません。
今回はshadcn/uiのインストール設定とテーマカスタマイズについて、特にCSS変数を使ってブランドデザインシステムを作る方法を紹介します。この記事を読み終われば、5分で基本設定ができ、1時間ほどでテーマを好みの色に調整できるようになります。
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をプロジェクトの「最初の依存関係」として扱い、後で追加しないように。痛い目を見ました。
方法2:手動インストール(既存プロジェクト向け)
プロジェクトがすでに完成に近く、CLIによる設定上書きのリスクが高い場合、手動でインストールします。
ステップは以下の通り:
ステップ1:Tailwind CSSがインストールされているか確認
shadcnのコンポーネントはTailwindでスタイリングされているので、まだなら先にTailwindをインストールします。公式ドキュメントが分かりやすいです。
ステップ2:依存関係をインストール
npm install class-variance-authority clsx tailwind-merge
npm install lucide-react
class-variance-authority(略称CVA)は便利です。後でコンポーネントバリアントを作る時に使います。
ステップ3:パスエイリアスを設定
tsconfig.json に追加:
{
"compilerOptions": {
"paths": {
"@/*": ["./*"]
}
}
}
これで @/components/ui/button という形式でコンポーネントをimportでき、../../../ を書く必要がなくなります。
ステップ4: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のユーティリティクラスではなく、CSS変数でテーマを作ることを意味します。
ステップ5:スタイルを追加
globals.css にshadcnのベーススタイルを追加します。テーマの説明で詳しく触れます。
2. テーマシステムを理解する: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() と透明度を追加してくれます。賢い設計です。
3. ブランドテーマをカスタマイズ
方法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:オンラインツールを使用
色を設定するのが面倒?オンラインツールを使いましょう。
メインカラーを選択すると、ツールがライトとダークの両方の完全なCSS変数セットを自動生成します。globals.css にコピペするだけです。
4. ダークモード設定
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"はクラス名でテーマを切り替えることを意味します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クラスをハードコード
<html lang="ja" className="dark">
これでテーマがダークに固定され、切り替えできなくなります。
方法2:デフォルトテーマを設定
<ThemeProvider
attribute="class"
defaultTheme="dark" // デフォルトダーク
enableSystem={false} // システム検出を無効化
>
ユーザーは手動で切り替えられますが、初期状態はダークになります。
5. 高度なカスタマイズ:コンポーネントバリアント
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更新もカスタマイズに影響しません。
6. よくある問題と注意点
問題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で独自のバリアントを作成し、デフォルトスタイルに依存しない
7. まとめ
shadcn/uiのインストール設定は実はシンプルです。重要なのは「依存パッケージではなくコードをコピーする」という設計理念を理解することです。利点は完全なコントロール、欠点は各プロジェクトでコンポーネントコードを自分でメンテナンスする必要があることです。
テーマカスタマイズに関しては、CSS変数システムはエレガントに設計されています。いくつかの変数値を変更するだけで、アプリ全体の色が更新されます。next-themesと組み合わせれば、ライト/ダークモード切り替えも数行のコードで実現できます。
最後のアドバイス:
- 新規プロジェクトではCLI初期化を優先—手動設定の手間を省ける
- セマンティックな色変数を使用—具体的な色名ではなく、primary、secondaryなどを使用
- ライトとダークモード両方でコントラストをテスト—読みやすさを確保
- ソースを変更せずラッパーコンポーネントを作成—更新を容易に
次にテーマ付きUIを素早く構築する必要がある時、shadcn/uiを試してみてください。コピペの喜び、使ってみれば分かります。
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コンポーネントのソースコードを直接変更すべき?
参考資料
- shadcn/ui 公式ドキュメント - Installation
- shadcn/ui 公式ドキュメント - Theming
- shadcn/ui 公式ドキュメント - Dark Mode
- Generate Custom shadcn/ui Themes
- Theming in shadcn UI: CSS Variables
4 min read · 公開日: 2026年3月26日 · 更新日: 2026年3月26日
関連記事
shadcn/uiとは?MUI/Chakra/Ant Designとの選び方
shadcn/uiとは?MUI/Chakra/Ant Designとの選び方
Tailwind CSS v4 新機能解説:パフォーマンス、設定、移行ガイド
Tailwind CSS v4 新機能解説:パフォーマンス、設定、移行ガイド
Tailwind v4 + Vite:5分で完了する完全設定テンプレート

コメント
GitHubアカウントでログインしてコメントできます