v0 について
Webアプリのデザインと開発に関するガイド型スキルです。ビジュアル設計、コンポーネント構成、Tailwind CSS、アクセシビリティ、パフォーマンスを扱い、一貫したUI実装を支援します。
主な機能
- 01カラーとタイポグラフィの指針
- 02レイアウトとレスポンシブ設計
- 03コンポーネント構成とコード整理
- 04Tailwind CSSのパターン
- 05アクセシビリティと性能の実践
活用シーン
- 01Webアプリの画面設計
- 02再利用可能なUIコンポーネントの整理
- 03レスポンシブ設計とアクセシビリティの確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ headline-design/ design-craft --skill v0インストール後、Claude Code で/v0を入力して読み込まれたか確認します。
同梱ファイルREADME.md
詳細
v0 デザイン&開発スキル
優れた UI/UX を備えた、プロフェッショナル品質で視覚的にも魅力的な Web アプリケーションを作成するための総合ガイドです。
目次
- デザイン哲学
- カラーシステム
- タイポグラフィ
- レイアウトと余白
- コンポーネントのアーキテクチャ
- Tailwind CSS のパターン
- アクセシビリティ
- パフォーマンス
- コードの構成
- UI/UX の原則
- 一般的なパターン
- 避けるべきアンチパターン
デザイン哲学
基本原則
- 足し過ぎず、抑制する — 優れたデザインとは、何を加えるかではなく、何を省くかです
- 巧妙さより明快さ — ユーザーがインターフェースをすぐに理解できるようにします
- 新しさより一貫性 — 予測しやすいパターンは認知負荷を軽減します
- 装飾より目的 — すべての要素に、そこにある理由が必要です
- 魅力的なものをリリースし、決して醜くしない — 創造性と仕上がりの美しさを両立させます
v0 の美学
- 余白を十分に取った、クリーンでモダンなインターフェース
- 邪魔にならずに奥行きを生み出す、控えめな影と境界線
- 視線を誘導する、滑らかで意図のあるアニメーション
- 統一感のある、プロフェッショナルなカラーパレット
- 明確な階層を生み出すタイポグラフィ
カラーシステム
3〜5 色のルール
必ず、色は合計でちょうど 3〜5 色を使用してください。 この制約により、統一感が生まれます。
必須の構成
1 Primary Brand Color → CTAs, key actions, brand identity
2-3 Neutrals → Backgrounds, text, borders
1-2 Accent Colors → Status indicators, highlights, secondary actions
色選びのガイドライン
| 用途 | 推奨事項 |
|---|---|
| 主なアクション | 彩度が高く、アクセシビリティに配慮したブランドカラー |
| 背景 | オフホワイト、ソフトグレー(広い領域には純白を使用しない) |
| テキスト | 黒に近い色(#0a0a0a〜#1a1a1a)。純粋な黒は使用しない |
| 境界線/区切り線 | ごく控えめなグレー(不透明度 10〜20%) |
| 成功状態 | ティール系のグリーン |
| エラー状態 | 刺激の強すぎない、暖色系の赤 |
| 警告状態 | アンバー/オレンジ系 |
色温度のルール
- 使う: 類似色。青→ティール、紫→ピンク、オレンジ→赤
- 使わない: 対照的な色温度の組み合わせ。ピンク→緑、オレンジ→青、赤→シアン
グラデーションのルール
- 明示的に求められない限り、グラデーションは避けてください — 単色のほうがすっきりします
- グラデーションが必要な場合:
- 控えめなアクセントとしてのみ使用し、主要な要素には使用しない
- 色の停止点は最大 2〜3 色
- 類似色のみを使用する
- グラデーションの方向を考慮する(通常は上から下、または斜め)
デザイントークンの構成
CSS 変数では、常に意味的なデザイントークンを使用します。
:root {
/* Backgrounds */
--background: 0 0% 100%;
--foreground: 0 0% 3.9%;
/* Cards & Surfaces */
--card: 0 0% 100%;
--card-foreground: 0 0% 3.9%;
/* Primary Actions */
--primary: 0 0% 9%;
--primary-foreground: 0 0% 98%;
/* Secondary Actions */
--secondary: 0 0% 96.1%;
--secondary-foreground: 0 0% 9%;
/* Muted Elements */
--muted: 0 0% 96.1%;
--muted-foreground: 0 0% 45.1%;
/* Accents */
--accent: 0 0% 96.1%;
--accent-foreground: 0 0% 9%;
/* Destructive Actions */
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 0 0% 98%;
/* Borders & Inputs */
--border: 0 0% 89.8%;
--input: 0 0% 89.8%;
--ring: 0 0% 3.9%;
/* Radius */
--radius: 0.5rem;
}
重要なルール: text-white、bg-black のような色の直接指定は決して使用しないでください。すべてトークンを通じてテーマを適用する必要があります。
タイポグラフィ
フォントは最大 2 種類のルール
フォントファミリーは必ず最大 2 種類までにしてください。 フォントが増えると、見た目にまとまりがなくなります。
フォントの組み合わせ方
Headings: Display or Sans-serif with personality (multiple weights)
Body: Highly readable sans-serif or serif
おすすめの組み合わせ
| スタイル | 見出し | 本文 |
|---|---|---|
| モダンテック | Inter, Geist | Inter, Geist |
| エディトリアル | Playfair Display | Source Sans Pro |
| スタートアップ | Cal Sans, Manrope | Inter |
| コーポレート | Outfit | System UI |
| クリエイティブ | Space Grotesk | DM Sans |
タイポグラフィのスケール
明確な階層を持つ、一貫したスケールを使用します。
/* Recommended Tailwind Classes */
text-xs → 12px → Fine print, labels
text-sm → 14px → Secondary text, captions
text-base → 16px → Body text (minimum for readability)
text-lg → 18px → Lead paragraphs
text-xl → 20px → Section headers
text-2xl → 24px → Card titles
text-3xl → 30px → Page sections
text-4xl → 36px → Hero subheadings
text-5xl → 48px → Hero headings
text-6xl+ → 60px+ → Display headings (use sparingly)
行の高さのルール
- 本文:
leading-relaxed(1.625)、またはleading-6〜leading-7 - 見出し:
leading-tight(1.25)、またはleading-snug(1.375) - 本文にはデフォルトの行の高さを決して使用しないでください。詰まりすぎています
テキストの折り返し
- 最適な位置で改行されるよう、タイトルを
text-balanceで囲みます - 重要なコピーには
text-prettyを使用します - 読みやすい行の長さにするため、
max-w-proseまたはmax-w-2xlを設定します
Next.js でのフォント実装
// layout.tsx
import { Inter, Playfair_Display } from 'next/font/google'
const inter = Inter({
subsets: ['latin'],
variable: '--font-sans'
})
const playfair = Playfair_Display({
subsets: ['latin'],
variable: '--font-serif'
})
export default function RootLayout({ children }) {
return (
<html className={`${inter.variable} ${playfair.variable}`}>
<body className="font-sans">{children}</body>
</html>
)
}
// tailwind.config.js
module.exports = {
theme: {
extend: {
fontFamily: {
sans: ['var(--font-sans)'],
serif: ['var(--font-serif)'],
},
},
},
}
レイアウトと余白
モバイルファーストのデザイン
必ずモバイルファーストでデザインし、その後、大きな画面向けに調整します。
// ✅ Mobile-first approach
<div className="px-4 md:px-6 lg:px-8">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3">
// ❌ Desktop-first (avoid)
<div className="px-8 md:px-6 sm:px-4">
レイアウト手法の優先順位
レイアウトを決める際は、次の優先順位に従ってください。
- Flexbox — ほとんどのレイアウト(ナビゲーションバー、カード、シンプルなグリッド)
- CSS Grid — 複雑な2次元レイアウト、ベントーグリッド、ダッシュボード
- 絶対配置 — 必要な場合に限る(モーダル、ツールチップ)
- floatは使用しない
余白のスケール
Tailwindの余白スケールを一貫して使用してください。
4px = p-1 → Tiny gaps (icon padding)
8px = p-2 → Small gaps (button padding)
12px = p-3 → Compact spacing
16px = p-4 → Standard spacing (most common)
24px = p-6 → Comfortable spacing
32px = p-8 → Section spacing
48px = p-12 → Large section gaps
64px = p-16 → Hero spacing
96px = p-24 → Major section dividers
余白のルール
// ✅ Use gap for flex/grid spacing
<div className="flex gap-4">
<div className="grid gap-6">
// ✅ Use padding for container spacing
<section className="px-4 py-12 md:px-6 lg:py-24">
// ❌ Avoid space-* utilities
<div className="space-y-4"> // Less flexible
// ❌ Never mix gap and margin on same element
<div className="flex gap-4 mb-4"> // Pick one approach
コンテナのパターン
// Standard content container
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
// Narrow content (articles, forms)
<div className="mx-auto max-w-2xl px-4">
// Full-bleed with contained content
<section className="w-full bg-muted">
<div className="mx-auto max-w-7xl px-4 py-16">
レスポンシブブレークポイント
sm: 640px → Large phones, small tablets
md: 768px → Tablets
lg: 1024px → Small laptops, tablets landscape
xl: 1280px → Desktops
2xl: 1536px → Large desktops
コンポーネントアーキテクチャ
ファイル構成
components/
├── ui/ # Base shadcn components (don't modify)
│ ├── button.tsx
│ ├── card.tsx
│ └── ...
├── [feature]/ # Feature-specific components
│ ├── feature-header.tsx
│ ├── feature-card.tsx
│ └── feature-list.tsx
├── layout/ # Layout components
│ ├── header.tsx
│ ├── footer.tsx
│ └── sidebar.tsx
└── shared/ # Shared/common components
├── logo.tsx
├── theme-toggle.tsx
└── loading-state.tsx
コンポーネント設計の原則
- 単一責任 — 各コンポーネントは1つのことを適切に行います
- 設定より合成 — シンプルなパーツから複雑なUIを構築します
- カスタマイズにはPropsを使用 — ハードコードされた値ではなく、Propsを使用します
- 適切なデフォルト値 — すぐに使用でき、必要に応じてカスタマイズできます
コンポーネントのテンプレート
import { cn } from "@/lib/utils"
interface FeatureCardProps {
title: string
description: string
icon?: React.ReactNode
className?: string
variant?: "default" | "highlighted"
}
export function FeatureCard({
title,
description,
icon,
className,
variant = "default"
}: FeatureCardProps) {
return (
<div
className={cn(
"rounded-lg border p-6 transition-colors",
variant === "default" && "bg-card hover:bg-accent",
variant === "highlighted" && "bg-primary text-primary-foreground",
className
)}
>
{icon && (
<div className="mb-4 text-muted-foreground">
{icon}
</div>
)}
<h3 className="font-semibold text-lg">{title}</h3>
<p className="mt-2 text-sm text-muted-foreground">
{description}
</p>
</div>
)
}
ページの構成
// app/feature/page.tsx
import { FeatureHero } from "@/components/feature/feature-hero"
import { FeatureGrid } from "@/components/feature/feature-grid"
import { FeatureCTA } from "@/components/feature/feature-cta"
export default function FeaturePage() {
return (
<main>
<FeatureHero />
<FeatureGrid />
<FeatureCTA />
</main>
)
}
モノリシックなページファイルは作成しないでください。 論理的なコンポーネントに分割してください。
Tailwind CSSのパターン
クラスの整理
クラスの順序を統一してください。
className={cn(
// 1. Layout (display, position, sizing)
"flex items-center justify-between",
"relative w-full max-w-md",
// 2. Spacing (margin, padding, gap)
"p-4 gap-2",
// 3. Typography
"text-sm font-medium",
// 4. Colors & Backgrounds
"bg-background text-foreground",
// 5. Borders & Shadows
"rounded-lg border shadow-sm",
// 6. Transitions & Animations
"transition-colors duration-200",
// 7. States (hover, focus, active)
"hover:bg-accent focus:ring-2",
// 8. Responsive overrides
"md:p-6 lg:flex-row"
)}
よく使うユーティリティパターン
// Centering
"flex items-center justify-center"
"grid place-items-center"
// Card pattern
"rounded-lg border bg-card p-6 shadow-sm"
// Interactive element
"cursor-pointer transition-colors hover:bg-accent"
// Focus ring (accessibility)
"focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2"
// Truncation
"truncate" // Single line
"line-clamp-2" // Multi-line (2 lines)
// Aspect ratios
"aspect-video" // 16:9
"aspect-square" // 1:1
// Backdrop blur (modals, overlays)
"bg-background/80 backdrop-blur-sm"
// Dividers
"divide-y divide-border"
// Screen reader only
"sr-only"
レスポンシブデザインのパターン
// Stack to row
<div className="flex flex-col gap-4 md:flex-row">
// Grid columns
<div className="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3">
// Hide/show
<div className="hidden md:block"> // Show on md+
<div className="md:hidden"> // Hide on md+
// Responsive text
<h1 className="text-3xl md:text-4xl lg:text-5xl">
// Responsive spacing
<section className="py-12 md:py-16 lg:py-24">
アニメーションのパターン
// Subtle hover lift
"transition-transform hover:-translate-y-1"
// Fade in on hover
"opacity-0 group-hover:opacity-100 transition-opacity"
// Scale on hover
"transition-transform hover:scale-105"
// Color transition
"transition-colors hover:bg-accent"
// Combined
"transition-all duration-200 hover:shadow-lg hover:-translate-y-0.5"
アクセシビリティ
必須の実践事項
セマンティックHTML
// ✅ Correct
<main>
<header>
<nav aria-label="Main navigation">
</header>
<article>
<h1>Page Title</h1>
<section aria-labelledby="section-heading">
<h2 id="section-heading">Section</h2>
</section>
</article>
<footer>
</main>
// ❌ Avoid
<div className="header">
<div className="nav">
<div className="main">
フォーカス管理
// Visible focus states
"focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2"
// Focus within (for form groups)
"focus-within:ring-2 focus-within:ring-ring"
// Skip link
<a
href="#main-content"
className="sr-only focus:not-sr-only focus:absolute focus:top-4 focus:left-4"
>
Skip to content
</a>
スクリーンリーダーのサポート
// Hidden but accessible text
<span className="sr-only">Open menu</span>
// Aria labels
<button aria-label="Close dialog">
<XIcon className="h-4 w-4" />
</button>
// Live regions for dynamic content
<div aria-live="polite" aria-atomic="true">
{statusMessage}
</div>
画像のアクセシビリティ
// Informative images
<img src="/chart.png" alt="Sales increased 25% in Q4 2024" />
// Decorative images
<img src="/decoration.png" alt="" role="presentation" />
// Complex images
<figure>
<img src="/diagram.png" alt="System architecture diagram" />
<figcaption>
Detailed description of the architecture...
</figcaption>
</figure>
色のコントラスト
- テキスト: コントラスト比を最低4.5:1にする(WCAG AA)
- 大きなテキスト: コントラスト比を最低3:1にする
- インタラクティブ要素: 視覚的に明確な違いを設ける
- 情報を伝える際に色だけに頼らない
キーボード操作
// Interactive elements must be keyboard accessible
<button>Clickable</button> // ✅ Naturally focusable
<div onClick={...}>Clickable</div> // ❌ Not keyboard accessible
// If you must use a div:
<div
role="button"
tabIndex={0}
onClick={handleClick}
onKeyDown={(e) => e.key === 'Enter' && handleClick()}
>
Clickable
</div>
パフォーマンス
画像の最適化
import Image from 'next/image'
// Always use Next.js Image component
<Image
src="/hero.jpg"
alt="Hero image description"
width={1200}
height={600}
priority // Above-the-fold images
className="object-cover"
/>
// Responsive images
<Image
src="/photo.jpg"
alt="Description"
fill
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
className="object-cover"
/>
コード分割
// Dynamic imports for heavy components
import dynamic from 'next/dynamic'
const HeavyChart = dynamic(() => import('@/components/heavy-chart'), {
loading: () => <ChartSkeleton />,
ssr: false // If client-only
})
読み込み状態
// Skeleton loading (preferred)
<div className="animate-pulse">
<div className="h-4 w-3/4 rounded bg-muted" />
<div className="mt-2 h-4 w-1/2 rounded bg-muted" />
</div>
// Spinner for actions
<Button disabled>
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
Loading...
</Button>
データ取得
// ✅ Server Components for static data
async function ProductList() {
const products = await getProducts()
return <ProductGrid products={products} />
}
// ✅ SWR for client-side data
import useSWR from 'swr'
function UserProfile() {
const { data, error, isLoading } = useSWR('/api/user', fetcher)
if (isLoading) return <ProfileSkeleton />
if (error) return <ErrorState />
return <Profile user={data} />
}
// ❌ Never fetch in useEffect
useEffect(() => {
fetch('/api/data').then(...) // Anti-pattern
}, [])
コードの整理
プロジェクト構成
app/
├── (marketing)/ # Route groups for layouts
│ ├── page.tsx
│ ├── about/
│ └── pricing/
├── (dashboard)/
│ ├── layout.tsx
│ └── dashboard/
├── api/
│ └── [feature]/
│ └── route.ts
├── layout.tsx
└── globals.css
components/
├── ui/ # shadcn components
├── [feature]/ # Feature components
├── layout/ # Layout components
└── shared/ # Shared components
lib/
├── utils.ts # Utility functions
├── validations.ts # Zod schemas
└── constants.ts # App constants
hooks/
├── use-[feature].ts
└── use-media-query.ts
types/
└── index.ts
命名規則
| 種類 | 規則 | 例 |
|---|---|---|
| コンポーネント | PascalCase | FeatureCard.tsx |
| ファイル | kebab-case | feature-card.tsx |
| フック | useを接頭辞とするcamelCase | useFeature.ts |
| ユーティリティ | camelCase | formatDate.ts |
| 型 | PascalCase | FeatureProps |
| 定数 | SCREAMING_SNAKE_CASE | MAX_FILE_SIZE |
| CSS変数 | kebab-case | --primary-color |
インポートの整理
// 1. React/Next.js
import { useState, useEffect } from 'react'
import Image from 'next/image'
import Link from 'next/link'
// 2. Third-party libraries
import { motion } from 'framer-motion'
import { z } from 'zod'
// 3. Internal components
import { Button } from '@/components/ui/button'
import { FeatureCard } from '@/components/feature/feature-card'
// 4. Internal utilities/hooks
import { cn } from '@/lib/utils'
import { useFeature } from '@/hooks/use-feature'
// 5. Types
import type { Feature } from '@/types'
UI/UXの原則
視覚的な階層
- サイズ — 大きな要素ほど先に目を引きます
- 色 — 彩度の高い色はニュートラルな色より目立ちます
- コントラスト — 強いコントラストは視線を集めます
- 余白 — ホワイトスペースによって重要な要素を際立たせます
- 位置 — 左上から右下へと読むパターン
インタラクティブ状態
すべてのインタラクティブ要素に次の状態を用意してください。
// Button example
<button className={cn(
// Default
"bg-primary text-primary-foreground",
// Hover
"hover:bg-primary/90",
// Focus
"focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
// Active/Pressed
"active:scale-[0.98]",
// Disabled
"disabled:pointer-events-none disabled:opacity-50"
)}>
フィードバックのパターン
// Loading feedback
<Button disabled={isLoading}>
{isLoading ? (
<>
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
Saving...
</>
) : (
'Save Changes'
)}
</Button>
// Success feedback
<div className="flex items-center gap-2 text-green-600">
<CheckCircle className="h-4 w-4" />
<span>Changes saved successfully</span>
</div>
// Error feedback
<div className="rounded-md bg-destructive/10 p-4 text-destructive">
<p className="text-sm font-medium">Error occurred</p>
<p className="mt-1 text-sm opacity-90">{error.message}</p>
</div>
空の状態
空白の画面を表示しないでください。常に役立つ空の状態を用意してください。
<div className="flex flex-col items-center justify-center py-12 text-center">
<InboxIcon className="h-12 w-12 text-muted-foreground/50" />
<h3 className="mt-4 text-lg font-semibold">No messages yet</h3>
<p className="mt-2 text-sm text-muted-foreground">
When you receive messages, they'll appear here.
</p>
<Button className="mt-4">
Send your first message
</Button>
</div>
マイクロインタラクション
UXを高めるさりげないアニメーション:
// Hover lift effect
"transition-transform duration-200 hover:-translate-y-1 hover:shadow-lg"
// Button press effect
"active:scale-[0.98] transition-transform"
// Smooth reveals
"animate-in fade-in slide-in-from-bottom-4 duration-300"
// Skeleton pulse
"animate-pulse"
よく使うパターン
ヒーローセクション
<section className="relative overflow-hidden py-24 md:py-32 lg:py-40">
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
<div className="mx-auto max-w-3xl text-center">
<h1 className="text-balance text-4xl font-bold tracking-tight md:text-5xl lg:text-6xl">
Your compelling headline here
</h1>
<p className="mt-6 text-pretty text-lg text-muted-foreground md:text-xl">
Supporting text that elaborates on the headline and provides context.
</p>
<div className="mt-8 flex flex-col gap-4 sm:flex-row sm:justify-center">
<Button size="lg">Primary Action</Button>
<Button size="lg" variant="outline">Secondary Action</Button>
</div>
</div>
</div>
</section>
機能グリッド
<section className="py-16 md:py-24">
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
<div className="mx-auto max-w-2xl text-center">
<h2 className="text-3xl font-bold md:text-4xl">Features</h2>
<p className="mt-4 text-muted-foreground">
Everything you need to succeed.
</p>
</div>
<div className="mt-12 grid gap-8 sm:grid-cols-2 lg:grid-cols-3">
{features.map((feature) => (
<FeatureCard key={feature.id} {...feature} />
))}
</div>
</div>
</section>
カードグリッド
<div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-3">
{items.map((item) => (
<Card key={item.id} className="group overflow-hidden">
<div className="aspect-video overflow-hidden">
<Image
src={item.image}
alt={item.title}
fill
className="object-cover transition-transform group-hover:scale-105"
/>
</div>
<CardHeader>
<CardTitle>{item.title}</CardTitle>
<CardDescription>{item.description}</CardDescription>
</CardHeader>
<CardFooter>
<Button variant="ghost" className="ml-auto">
Learn more <ArrowRight className="ml-2 h-4 w-4" />
</Button>
</CardFooter>
</Card>
))}
</div>
ベントーグリッド
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
{/* Large feature - spans 2 columns */}
<div className="md:col-span-2 lg:row-span-2 rounded-xl border bg-card p-6">
<h3 className="text-2xl font-bold">Main Feature</h3>
</div>
{/* Regular items */}
<div className="rounded-xl border bg-card p-6">
<h3 className="font-semibold">Feature 2</h3>
</div>
<div className="rounded-xl border bg-card p-6">
<h3 className="font-semibold">Feature 3</h3>
</div>
{/* Wide item - spans 2 columns */}
<div className="md:col-span-2 rounded-xl border bg-card p-6">
<h3 className="font-semibold">Wide Feature</h3>
</div>
</div>
フォームのレイアウト
<form className="space-y-6">
<div className="grid gap-4 sm:grid-cols-2">
<div className="space-y-2">
<Label htmlFor="firstName">First name</Label>
<Input id="firstName" placeholder="John" />
</div>
<div className="space-y-2">
<Label htmlFor="lastName">Last name</Label>
<Input id="lastName" placeholder="Doe" />
</div>
</div>
<div className="space-y-2">
<Label htmlFor="email">Email</Label>
<Input id="email" type="email" placeholder="[email protected]" />
<p className="text-sm text-muted-foreground">
We'll never share your email.
</p>
</div>
<Button type="submit" className="w-full sm:w-auto">
Submit
</Button>
</form>
ナビゲーション
<header className="sticky top-0 z-50 w-full border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
<div className="mx-auto flex h-16 max-w-7xl items-center justify-between px-4 sm:px-6 lg:px-8">
<Link href="/" className="flex items-center gap-2">
<Logo className="h-8 w-8" />
<span className="font-bold">Brand</span>
</Link>
<nav className="hidden items-center gap-6 md:flex">
<Link href="/features" className="text-sm font-medium text-muted-foreground transition-colors hover:text-foreground">
Features
</Link>
<Link href="/pricing" className="text-sm font-medium text-muted-foreground transition-colors hover:text-foreground">
Pricing
</Link>
</nav>
<div className="flex items-center gap-4">
<Button variant="ghost" size="sm" className="hidden sm:flex">
Sign in
</Button>
<Button size="sm">Get Started</Button>
</div>
</div>
</header>
避けるべきアンチパターン
色の間違い
// ❌ Too many colors
className="bg-purple-500 text-pink-400 border-blue-300 shadow-green-200"
// ❌ Direct colors instead of tokens
className="bg-white text-black"
// ❌ Purple/violet as primary (unless explicitly requested)
className="bg-violet-600"
// ❌ Clashing temperature gradients
className="bg-gradient-to-r from-pink-500 to-green-500"
// ✅ Semantic tokens
className="bg-background text-foreground"
タイポグラフィの間違い
// ❌ Too many fonts
<h1 className="font-display">
<p className="font-body">
<span className="font-accent">
<code className="font-mono"> // 4 fonts!
// ❌ Tiny text
className="text-xs" // Avoid for body text
// ❌ No line-height consideration
className="text-base" // Missing leading-*
// ✅ Proper typography
className="text-base leading-relaxed"
レイアウトの間違い
// ❌ Desktop-first responsive
className="w-1/3 sm:w-1/2 xs:w-full"
// ❌ Using space-* utilities
className="space-y-4"
// ❌ Floats
className="float-left"
// ❌ Mixing gap and margin
className="flex gap-4 mb-4"
// ✅ Mobile-first with gap
className="flex flex-col gap-4 md:flex-row"
コンポーネントの間違い
// ❌ Monolithic page files (500+ lines)
// ❌ Hardcoded values instead of props
// ❌ Inline styles
// ❌ Non-semantic HTML (div for everything)
// ❌ Missing key props in lists
// ❌ Fetching in useEffect
// ✅ Split into components
// ✅ Use props for customization
// ✅ Tailwind classes
// ✅ Semantic HTML
// ✅ Proper key props
// ✅ Server Components or SWR
アクセシビリティの間違い
// ❌ Click handler on div
<div onClick={handleClick}>Click me</div>
// ❌ Missing alt text
<img src="/photo.jpg" />
// ❌ Color-only indication
<span className="text-red-500">Error</span>
// ❌ Missing focus states
<button className="hover:bg-accent">
// ✅ Use button element
<button onClick={handleClick}>Click me</button>
// ✅ Descriptive alt text
<img src="/photo.jpg" alt="Team meeting in conference room" />
// ✅ Icon + color for errors
<span className="flex items-center gap-2 text-destructive">
<AlertCircle className="h-4 w-4" />
Error message
</span>
// ✅ Focus states
<button className="hover:bg-accent focus:ring-2 focus:ring-ring">
視覚面の間違い
// ❌ Abstract decorative shapes
<div className="absolute -top-20 -right-20 h-40 w-40 rounded-full bg-gradient-to-r from-purple-400 to-pink-400 blur-3xl" />
// ❌ Placeholder images left in production
<img src="/placeholder.jpg" />
// ❌ Emojis as icons
<span>📧 Email</span>
// ❌ Hand-drawn SVG maps
<svg><path d="M100,200 L300,400..." /></svg>
// ✅ Real images or GenerateImage tool
// ✅ Proper icon libraries (Lucide, etc.)
// ✅ Mapping libraries for geographic data
クイックリファレンスチェックリスト
リリース前に、次の項目を確認してください。
- 色: 最大3〜5色、セマンティックトークンを使用
- タイポグラフィ: フォントは最大2種類、適切な階層を設定
- 余白: 一貫性を保ち、Tailwindのスケールを使用
- モバイル: 幅375pxで適切に表示
- アクセシビリティ: キーボード操作、フォーカス状態、代替テキスト
- パフォーマンス: 画像を最適化し、コードを分割
- コンポーネント: 論理的に分割し、モノリシックにしない
- 読み込み: 非同期コンテンツにはスケルトン状態を用意
- 空の状態: データがない場合に役立つメッセージを表示
- エラー: 明確なエラーメッセージと復旧手段を用意
- インタラクション: ホバー、フォーカス、アクティブ状態を定義
概要
v0 のアプローチは、次のように要約できます。
控えめなエレガンスと、目的に沿ったインタラクション。
すべてのデザイン上の判断は、次の基準を満たす必要があります。
- 明瞭さを高めるものですか?
- 一貫性を保つものですか?
- ユーザーの目的に役立つものですか?
- 取り除くとデザインが損なわれますか?
4 つすべてに「はい」と答えられない場合は、その選択を見直してください。