pixel-perfect-replication について
スクリーンショット、モックアップ、デザイン画像をもとに UI を実装するためのスキルです。参照画像を仕様として段階的に視覚情報を抽出し、不明点は推測せず確認します。
主な機能
- 01参照画像とビューポートの分類
- 02レイアウトとタイポグラフィの抽出
- 03色と間隔の体系化
- 04コンポーネントのスタイルと質感の整理
- 05レスポンシブ要素と操作の手掛かりの分析
活用シーン
- 01Webサイトのスクリーンショットからページを再現
- 02Figma エクスポートを UI コードに変換
- 03モバイル画像からコンポーネント配置を再現
- 04コーディング前に不明確なデザイン要素を特定
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ yu-369/ vibecurb --skill pixel-perfect-replicationインストール後、Claude Code で/pixel-perfect-replicationを入力して読み込まれたか確認します。
詳細
ピクセル単位で忠実にデザインを再現
ユーザーがスクリーンショット、モックアップ、Figma のエクスポート、その他のデザイン画像を提示し、コードでの再現を依頼したときに、このスキルが起動します。参照画像が仕様です。あなたの役割はデザイナーではなく、翻訳者です。フォントサイズ、間隔、色、角丸、影、レイアウトの比率など、あらゆる視覚的な判断は画像から導き出してください。自分の好みで決めてはいけません。
パイプライン
すべての再現タスクはこのフローに従います。フェーズを省略してはいけません。前のフェーズが完了する前に、次のフェーズを開始してはいけません。
┌─────────────────────────────────────────────────────────────────────┐
│ │
│ IMAGE IN ──→ Phase 1: Intake ──→ Phase 2: Deep Extraction │
│ (classify) (7 layers, fill sheets) │
│ │
│ ──→ Phase 3: Build │
│ (structure-first, exact CSS) │
│ │
│ ──→ Phase 4: Visual Diff │
│ (verify against reference) │
│ │
│ Each phase has a ✓ Quality Gate. Failing a gate blocks the next. │
│ │
└─────────────────────────────────────────────────────────────────────┘
フェーズ 1:画像の受け取り
参照画像を受け取ります。何かを始める前に、まず何を見ているのかを分類してください。
→ 画像を分類する
参照画像ごとに、次の表を記入してください。
| 項目 | 回答 |
|---|---|
| 画像の種類 | ページ全体のスクリーンショット / 単一セクション / コンポーネントの詳細 / モバイル表示 / デスクトップ表示 / Figma フレーム / デザインツールのエクスポート / 公開サイトのスクリーンショット |
| 表示されているセクション | 上から順に列挙します。例:「ナビゲーション → ヒーロー → 特長 → お客様の声 → フッター」 |
| 対象ビューポート | 推定幅:1440px(デスクトップ)、1280px(ノートパソコン)、768px(タブレット)、375px(モバイル) |
| 忠実度 | 高解像度エクスポート(サブピクセルの詳細も意図的) / 圧縮されたスクリーンショット(非可逆圧縮の影響が一部あり) |
| テーマ | ライト / ダーク / 混合 |
→ 抽出サマリーを出力する
コードを書く前に、見えている内容を構造化した自然な言葉で説明してください。これが、以降の判断の基準になります。
例:
ライトモード、1440px のデスクトップ表示。5 つのセクション:左にロゴ、中央にリンク、右に CTA がある、すりガラス調で固定表示されるナビゲーション。画面いっぱいの写真に重なる、左揃えの大きなセリフ体見出しを配置したヒーロー。アイコンを上部に配したカードによる 3 列の特長グリッド。大きな引用符を使ったお客様の声のカルーセル。4 列のリンクグリッドを備えたシンプルなフッター。配色:温かみのあるクリーム色のベース、ほぼ黒のテキスト、CTA にテラコッタのアクセント。タイポグラフィ:セリフ体のディスプレイ見出し(おそらく Playfair Display)、幾何学的なサンセリフ体の本文(おそらく Outfit)。カードは角が直角で、ボタンはピル型です。目に見える影はなく、控えめな境界線で区切られたフラットなデザインです。
→ 画像が不鮮明な場合
推測してはいけません。具体的に質問してください。
「この解像度ではナビゲーションのリンクが詰まっていて読めません。本文のフォントは Outfit か Satoshi のようですが、このサイズでは形状がほぼ同じです。ナビゲーション部分を拡大した画像を提供していただくか、フォントスタックをご確認いただけますか?」
✓ 品質ゲート:受け取り
フェーズ 2 に進む前に、次の点を確認してください。
- 画像の種類、セクション数、ビューポート、忠実度を分類した
- 抽出サマリーを記述した
- 不明瞭な箇所を明示し、説明を求めた(またはすべて判読できることを確認した)
フェーズ 2:詳細な抽出
参照画像に対して、7 つの抽出レイヤーをすべて実行します。各レイヤーはデザインの 1 つの側面に注目します。それぞれについて抽出シートに記入してください。レイヤーを省略すると再現にずれが生じます。ここでの小さな誤差が積み重なり、最終的な実装が「何か違う」ものになります。
レイヤー 1:レイアウトグリッド
空間的な骨組みを抽出します。
抽出シート:
| プロパティ | 測定値 |
|---|---|
| コンテナーの最大幅 | 例:1280px、1440px - ビューポートの端との比率から測定 |
| カラム構成 | 例:grid-cols-[1.15fr_1fr]、grid-cols-3、single column centered |
| 水平方向のパディング | 例:px-6 md:px-12 lg:px-20 - コンテンツの端とビューポートの端の間隔を測定 |
| セクションの高さ | ビューポート全体を使う場合は min-h-[100dvh]、コンテンツに応じて決まる場合は auto |
| セクション間隔 | セクション間の垂直方向の間隔。例:py-24 lg:py-32 |
| 配置 | セクションごとに、左/中央/右/混在 |
| Z軸の重ね合わせ | 重なりはありますか? 要素がほかの要素の上に配置されていますか? |
画像から比率を測定する方法:
- ヒーローの見出しがビューポート幅の約60%を占める場合、ターゲットが1440pxなら、およそ
max-w-[54rem]です - 1つのカラムが隣のカラムより見た目で1.5倍広い場合は、
grid-cols-[1.5fr_1fr]を使用します - 見出しの上の空白が見出しのフォントサイズの約2倍ある場合、パディングは見出しに対しておよそ
2emです
⚠ レイアウトのずれに注意: 最もよくあるレイアウトの誤りは、コンテナーの最大幅を間違えることです。max-w-[1200px] のデザインは max-w-[1440px] のデザインとは見た目が大きく異なり、余白の比率がまったく変わります。慎重に測定してください。
レイヤー 2:タイポグラフィ
最も重要な抽出項目です。タイポグラフィの誤りは、再現したデザインが「何か違う」と感じられる最大の原因です。
抽出シート(表示されているすべてのテキスト要素について記入してください):
| 要素 | フォントファミリー | ウェイト | サイズ | 行の高さ | 字間 | 変換 | 色 |
|---|---|---|---|---|---|---|---|
| ナビゲーションリンク | |||||||
| アイブロウ/ラベル | |||||||
| H1(ヒーロー) | |||||||
| H2(セクション) | |||||||
| H3(カードタイトル) | |||||||
| 本文 | |||||||
| キャプション/メタデータ | |||||||
| CTA テキスト | |||||||
| フッターリンク |
フォントの識別方法 — 確認するポイント:
フォントは特定の文字に特徴が表れます。推測する前に、次の点を確認してください。
| 確認する文字 | わかること |
|---|---|
小文字の a | 1階建て(Geist、Helvetica)か、2階建て(Outfit、Satoshi、DM Sans)か |
小文字の g | 開いたテール(ほとんどのサンセリフ)か、閉じたテール(Futura、一部のジオメトリック系)か |
小文字の t | 曲線の横棒(ヒューマニスト系:Manrope、Jakarta)か、直線の横棒(ジオメトリック系:Outfit、Satoshi)か |
大文字の R | 直線の脚(Geist、Helvetica)か、曲線の脚(Outfit、Satoshi)か |
大文字の Q | テールの形はフォントによって大きく異なるため、強い識別要素になります |
小文字の e | 高い位置の横棒(ジオメトリック系)か、中央の横棒(ヒューマニスト系)か |
数字の 1, 4, 6, 9 | フォントごとに形状が大きく異なります |
一般的なウェブフォントのクイックリファレンス:
| 見た目の特徴 | 有力候補 |
|---|---|
ジオメトリック系、2階建ての a、丸いカウンター | Outfit、Satoshi、DM Sans、Plus Jakarta Sans |
グロテスク系、1階建ての a、フラットな端部 | Geist、Suisse Intl、Helvetica Neue |
| ヒューマニスト系、開いたカウンター、カリグラフィー調のストレス | Manrope、Plus Jakarta Sans、Nunito Sans |
| コンデンス系、高い x ハイト | Barlow Condensed、Oswald、Archivo Narrow |
| モダンセリフ、高いコントラスト、鋭いセリフ | Playfair Display、Bodoni Moda |
| トランジショナルセリフ、中程度のコントラスト | Lora、Merriweather、Source Serif Pro |
| ディスプレイサンセリフ、幅広、太字 | Cabinet Grotesk、Clash Display、Monument Extended |
| 等幅 | JetBrains Mono、Fira Code、IBM Plex Mono、Geist Mono、Space Mono |
フォントを確信を持って特定できない場合は、有力候補を2〜3個挙げ、どの特徴的な文字からその候補を選んだか説明してください。例:「2階建ての『a』と丸い『o』からOutfitが有力ですが、端部がやや四角いためSatoshiの可能性もあります。ひとまずOutfitを使用し、誤っていた場合は --font-display を変更してください。」
⚠ 差異に関する警告: 「見出しは太字」という理由だけで、見出しを font-weight: 700 と決めつけないでください。高級感のあるデザインでは、より太い書体を使いながら、見出しのウェイトを 500 や 600 にすることがよくあります。カウンターの広さに対するストロークの太さを確認してください。
レイヤー 3:カラーパレット
異なる色をすべて抽出します。「青を使っている」ではなく、16 進数の値を抽出してください。
抽出シート:
| 役割 | 16 進数の値 | 備考 |
|---|---|---|
| 背景(プライマリ) | 例:#F5F0EB の温かみのあるクリーム色。単なる #FFFFFF ではありません | |
| 背景(セカンダリ) | セクションの背景色やカードの背景色 | |
| 背景(ダークセクション) | 暗い背景に切り替わるセクションがある場合 | |
| テキスト(プライマリ) | プライマリ背景上の見出しと本文のテキスト | |
| テキスト(セカンダリ) | 控えめな説明文やメタデータ | |
| テキスト(ターシャリ) | プレースホルダーや無効状態 | |
| アクセント | CTA、アクティブ状態のインジケーター、リンク | |
| アクセント(ホバー) | 操作時に使う、より暗い/明るい色のバリエーション | |
| ボーダー | カードの枠線、区切り線、入力欄の枠線 | |
| 影 | 色味が付いている場合は、その色相を記載 |
圧縮されたスクリーンショットからの色の抽出:
スクリーンショットでは色が圧縮されます。正確な値を得るには:
- エッジや JPEG の圧縮ノイズではなく、色の最も広い単色領域からサンプリングします
- 一般的なウェブカラーと照合します。測定値が
#0b0b0bなら、ほぼ間違いなく標準的なオフブラックの#0a0a0aです。#f4f3f1なら、よく使われる温かみのあるクリーム色の#f5f4f2である可能性が高いです - 抽出後、テキスト色と背景色の WCAG AA コントラストを確認し、値が妥当であることを検証します
⚠ ずれに関する警告: #FFFFFF(純白)と #F5F0EB(温かみのあるクリーム色)の違いで、ページの印象は大きく変わります。参照画像が純色を明確に示していない限り、#FFFFFF や #000000 を安易に使わないでください。高級感のあるデザインの多くは、オフホワイトやオフブラックを使用します。
レイヤー 4:スペーシングシステム
スペーシングが、「近い見た目」と「そっくりな見た目」を分けます。
抽出シート:
| 測定項目 | 値 | 確認方法 |
|---|---|---|
| 基本単位 | 4px または 8px | 繰り返し使われている最小の間隔を測定 |
| ボタンのパディング(横) | 例:24px / px-6 | テキストの端からボタンの端までの水平方向の間隔 |
| ボタンのパディング(縦) | 例:12px / py-3 | 垂直方向の間隔 |
| カード内部のパディング | 例:32px / p-8 | カードの端から内容までの間隔 |
| グリッド間隔 | 例:24px / gap-6 | カードや列の間隔 |
| 見出し → 補足テキスト | 例:16px / mt-4 | 見出しのベースラインから補足テキスト上端までの間隔 |
| 補足テキスト → CTA | 例:32px / mt-8 | 補足テキストからボタンまでの間隔 |
| セクションのパディング(上) | 例:96px / pt-24 | セクション上端から最初の要素までの間隔 |
| セクションのパディング(下) | 例:128px / pb-32 | 最後の要素からセクション下端までの間隔 |
| ナビゲーションの高さ | 例:64px / h-16 | ナビゲーションバー全体の高さ |
| ナビゲーションリンクの間隔 | 例:32px / gap-8 | ナビゲーションリンク同士の間隔 |
⚠ ずれに関する警告: セクションの上と下のパディングは、同じとは限りません。視覚的なバランスを取るため、上より下のパディングを大きくする(またはその逆の)デザインも多くあります。参照画像が pt-20 pb-28 なのに、py-24 と決めつけないでください。上下をそれぞれ個別に測定します。
レイヤー 5:コンポーネント一覧
画像に表示されている異なる UI コンポーネントをすべて書き出します。
各コンポーネントについて、以下を記入します:
| コンポーネント | 形状(角丸) | 枠線 | 影 | 背景 | 表示されている状態 | アイコンのスタイル |
|---|---|---|---|---|---|---|
| プライマリボタン | ||||||
| セカンダリボタン | ||||||
| カード | ||||||
| 入力欄 | ||||||
| バッジ/ピル | ||||||
| アバター | ||||||
| ナビゲーション | ||||||
| 区切り線 |
角丸の一貫性チェック: 多くのデザインでは、角丸のスタイルが統一されています。以下のどれが使われているか確認します:
- シャープ - すべて
0px(ブルータリスト、エディトリアル) - 控えめ - すべて
4-8px(SaaS、製品) - 丸みあり - すべて
12-16px(モダン、親しみやすい) - ピル型 - ボタンは
9999px、カードは丸みあり(高級感、洗練) - 混在 - コンポーネントごとに異なる角丸(それぞれを確認)
⚠ ずれに関する警告: 参照画像のボタンがピル型(rounded-full)なら、コードで rounded-lg にしてはいけません。角丸の不一致はすぐに目につきます。目は、色やスペーシングの誤りよりも早くそれを検出します。
レイヤー 6: 雰囲気とテクスチャ
デザインを生き生きと感じさせるか、平坦に感じさせるかの微妙なディテールを抽出します。
抽出シート:
| プロパティ | あり? | 詳細 |
|---|---|---|
| ノイズ/グレインオーバーレイ | あり/なし | 不透明度レベル (通常は 0.03-0.06) |
| 放射状アンビエントグロー | あり/なし | 位置、色、広がり |
| フロストガラス (backdrop-blur) | あり/なし | どの要素に、ぼかし量 |
| グラデーション背景 | あり/なし | 方向、ストップ、色 |
| 色付きシャドウ | あり/なし | 黒だけでなく、シャドウの色相 |
| 画像オーバーレイ/スクリム | あり/なし | グラデーションの方向、不透明度 |
| 背景画像/パターン | あり/なし | 微妙なテクスチャ、ドット、ライン |
| 奥行き/レイヤーの感覚 | フラット / 微妙 / 強い | 全体的なシャドウの使用 |
レイヤー 7: レスポンシブの手がかりとインタラクションの推測
静的な画像からでも、動作に関する手がかりを抽出します。
抽出シート:
| シグナル | 推測 |
|---|---|
| マルチカラムレイアウト | 768px 未満ではシングルカラムに折りたたまれる |
| 水平ナビゲーションバー | 768px 未満ではモバイルメニューが必要になる |
| 固定されているように見えるナビ | position: fixed; top: 0 と backdrop-blur が使われている可能性が高い |
| 「ちょうど着地した」ように配置された要素 | エントリーアニメーションが示唆される (スタッガー付きのフェードアップ) |
| 視覚的な奥行きのあるボタン | ホバーで浮き上がる (translateY(-1px)、シャドウの増加) |
| ボーダー付きのカード | ホバーでボーダー色の変化、または微妙な背景の変化 |
| 画像付近のドットインジケーター | カルーセル/スライダーコンポーネント |
| アクティブ/選択中のタブスタイル | 状態管理を伴うタブコンポーネント |
| 表示されているフォーム入力 | フォーカスリング、バリデーション状態が必要 |
✓ 品質ゲート: 抽出
フェーズ 3 に進む前に、以下を確認してください:
- 7 つの抽出シートがすべて記入されている
- フォント候補が根拠とともに特定されている
- すべての異なる色に 16 進数値がある
- スペーシングの値が仮定ではなく、測定されている
- コンポーネントの一覧が完全で、コンポーネントごとに角丸、ボーダー、シャドウが記録されている
- 不明な点はユーザーに報告されている
フェーズ 3: ビルド
ここから実装を開始します。以下の正確なビルド順に従ってください。各ステップはその前のステップに依存します。
→ ステップ 1: グローバル基盤
最初にデザイントークンを設定します。他のすべてはこれらを参照します。
/* BLUEPRINT: Global tokens
WHY: Setting these first means every component inherits
the correct base values. Changing a token here updates
the entire page. */
@import url('https://fonts.googleapis.com/css2?family=FONT_NAME:wght@300;400;500;600;700&display=swap');
:root {
/* Colors - from Extraction Sheet Layer 3 */
--color-bg: #____;
--color-surface: #____;
--color-text: #____;
--color-text-2: #____;
--color-text-3: #____;
--color-accent: #____;
--color-accent-hover: #____;
--color-border: rgba(_, _, _, _);
/* Typography - from Extraction Sheet Layer 2 */
--font-display: 'FONT_NAME', Georgia, serif;
--font-body: 'FONT_NAME', system-ui, sans-serif;
--font-mono: 'FONT_NAME', monospace;
/* Spacing - from Extraction Sheet Layer 4 */
--space-section: clamp(5rem, 10vw, 8rem);
--space-component: 2rem;
--space-element: 1rem;
/* Radius - from Extraction Sheet Layer 5 */
--radius-card: __px;
--radius-button: __px;
--radius-input: __px;
}
*,
*::before,
*::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: var(--font-body);
font-size: 1rem; /* Adjust if reference base is not 16px */
line-height: 1.6; /* From extraction */
color: var(--color-text);
background-color: var(--color-bg);
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
→ ステップ 2: レイアウトの骨組み
正しい寸法でセクションコンテナを構築します。まだコンテンツは入れません。ボックスだけです。
/* BLUEPRINT: Section containers
WHY: Getting the spatial structure right first prevents
cascading spacing errors when content is added. */
.section {
width: 100%;
max-width: ____px; /* From Layer 1 extraction */
margin: 0 auto;
padding: var(--space-section) clamp(1.5rem, 5vw, 5rem);
}
/* Full-viewport section */
.section--full {
min-height: 100dvh;
/* WHY dvh not vh: vh causes a layout jump on iOS Safari
when the address bar collapses. dvh accounts for this. */
display: flex;
flex-direction: column;
justify-content: center;
}
/* Grid layouts - adjust columns to match reference */
.grid-2-asymmetric {
display: grid;
grid-template-columns: 1.15fr 1fr; /* From Layer 1 */
align-items: center;
gap: 4rem;
}
.grid-3-equal {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1.5rem; /* From Layer 4 */
}
@media (max-width: 768px) {
.grid-2-asymmetric,
.grid-3-equal {
grid-template-columns: 1fr;
gap: 2rem;
}
}
→ ステップ 3: タイポグラフィの調整
レイヤー 2 の抽出シートからすべてのテキストスタイルを適用します。
/* BLUEPRINT: Typography scale
WHY: Every property is explicitly set from the extraction.
Never rely on browser defaults - they will drift. */
.heading-display {
font-family: var(--font-display);
font-size: clamp(2.5rem, 6vw, 5rem); /* From extraction */
font-weight: 700; /* Verified from stem thickness, not assumed */
line-height: 0.95; /* Tight - measured from baseline gap */
letter-spacing: -0.03em; /* Negative - measured from character proximity */
color: var(--color-text);
text-wrap: balance;
max-width: 18ch; /* Prevents 4+ line wraps */
}
.heading-section {
font-family: var(--font-display);
font-size: clamp(1.75rem, 4vw, 3rem);
font-weight: 600;
line-height: 1.1;
letter-spacing: -0.02em;
color: var(--color-text);
}
.body-text {
font-family: var(--font-body);
font-size: clamp(0.9375rem, 1.1vw, 1.125rem);
font-weight: 400;
line-height: 1.65;
color: var(--color-text-2);
max-width: 55ch; /* Comfortable reading width */
}
.eyebrow {
font-family: var(--font-mono);
font-size: 0.6875rem;
font-weight: 500;
letter-spacing: 0.18em;
text-transform: uppercase;
color: var(--color-text-3);
}
.caption {
font-size: 0.8125rem;
line-height: 1.5;
color: var(--color-text-3);
}
⚠ ドリフト警告: フォントサイズを都合のよい値に丸めないでください。抽出結果の本文テキストが 15px であれば、1rem ではなく 0.9375rem を使用します。見出しが 72px に見える場合は、5rem ではなく 4.5rem を使用します。丸めはページ全体で蓄積されます。
→ ステップ 4: コンポーネントの調整
レイヤー 5 の抽出シートから各コンポーネントを構築します。
/* BLUEPRINT: Button - primary
WHY: Padding, radius, and font-size are from the extraction.
The transition easing (0.16, 1, 0.3, 1) gives a snappy
deceleration that feels physical. */
.btn-primary {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
padding: 0.75rem 1.5rem; /* From Layer 4 */
font-family: var(--font-body);
font-size: 0.875rem; /* From Layer 2 */
font-weight: 600;
letter-spacing: 0.04em; /* Only if extraction shows tracking */
text-transform: uppercase; /* Only if extraction shows uppercase */
border-radius: var(--radius-button);
background: var(--color-accent);
color: #FFFFFF;
border: none;
cursor: pointer;
text-decoration: none;
transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1);
}
.btn-primary:hover {
background: var(--color-accent-hover);
transform: translateY(-1px);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
}
.btn-primary:active {
transform: translateY(0) scale(0.98);
}
.btn-primary:focus-visible {
outline: 2px solid var(--color-accent);
outline-offset: 2px;
}
/* BLUEPRINT: Button - ghost/outline */
.btn-ghost {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
padding: 0.75rem 1.5rem;
font-family: var(--font-body);
font-size: 0.875rem;
font-weight: 500;
border-radius: var(--radius-button);
background: transparent;
color: var(--color-text);
border: 1px solid var(--color-border);
cursor: pointer;
text-decoration: none;
transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1);
}
.btn-ghost:hover {
border-color: var(--color-text);
background: rgba(0, 0, 0, 0.03);
}
/* BLUEPRINT: Card */
.card {
background: var(--color-surface);
border-radius: var(--radius-card);
padding: var(--space-component);
border: 1px solid var(--color-border);
/* Shadow: only add if extraction shows shadow */
}
/* BLUEPRINT: Navigation */
.nav {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 50;
height: 64px; /* From Layer 4 extraction */
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 clamp(1.5rem, 5vw, 5rem);
background: rgba(255, 255, 255, 0.85); /* Adjust to match */
backdrop-filter: blur(16px);
-webkit-backdrop-filter: blur(16px);
border-bottom: 1px solid var(--color-border);
}
.nav-link {
font-size: 0.875rem;
font-weight: 500;
color: var(--color-text-2);
text-decoration: none;
transition: color 0.2s ease;
}
.nav-link:hover {
color: var(--color-text);
}
→ ステップ 5: スペーシングの調整
すべての要素の間隔を確認し、レイヤー 4 の抽出シートと照合します。ここが実装で最もずれが生じやすい箇所です。
→ ステップ 6: 雰囲気の調整
レイヤー 6 の抽出シートからテクスチャと奥行きを追加します。参照画像に表示されているものだけを追加してください。
/* BLUEPRINT: Noise/grain overlay
WHY: Breaks digital flatness. Only add if the reference
shows subtle texture on the background.
Uses position:fixed so the grain doesn't scroll. */
.grain-overlay {
position: fixed;
inset: 0;
pointer-events: none;
z-index: 9999;
opacity: 0.04; /* Adjust to match reference intensity */
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='1'/%3E%3C/svg%3E");
}
/* BLUEPRINT: Ambient radial glow
WHY: Adds depth to flat dark backgrounds. Only use if the
reference shows a subtle light center. */
.ambient-glow {
position: absolute;
inset: 0;
background: radial-gradient(
ellipse 60% 50% at 50% 40%,
rgba(255, 255, 255, 0.035) 0%,
transparent 70%
);
pointer-events: none;
}
/* BLUEPRINT: Frosted glass surface
WHY: For navs or overlays that show content blurring through.
saturate(180%) makes colors pop through the blur layer. */
.surface-frosted {
background: rgba(255, 255, 255, 0.8);
backdrop-filter: blur(20px) saturate(180%);
-webkit-backdrop-filter: blur(20px) saturate(180%);
}
⚠ ドリフト警告: 参照画像に表示されていない場合は、グレイン、グロー、ぼかしを追加しないでください。これらは雰囲気のディテールであり、デフォルトではありません。参照画像にないテクスチャを追加することは、再現ではなく解釈です。
→ ステップ 7: レスポンシブの調整
参照画像がデスクトップのみの場合、レイアウト構造からモバイルの動作を推測します。デスクトップとモバイルの両方の参照画像が提供されている場合は、両方に正確に合わせます。
/* BLUEPRINT: Mobile collapse
WHY: Every multi-column layout must collapse to single-column.
Touch targets must be minimum 44px for accessibility. */
@media (max-width: 768px) {
.grid-2-asymmetric,
.grid-3-equal {
grid-template-columns: 1fr;
}
.heading-display {
/* clamp() already handles this, but verify the minimum */
max-width: 100%;
}
.nav {
/* May need a hamburger menu implementation */
}
/* Touch targets */
.btn-primary,
.btn-ghost,
.nav-link {
min-height: 44px;
}
}
→ ステップ 8: インタラクションの調整
ホバー状態とエントリーアニメーションを追加します。静的画像ではインタラクションを表示できませんが、すべてのインタラクティブ要素にはフィードバックが必要です。
/* BLUEPRINT: Staggered entry animation
WHY: Elements that fade+slide in feel intentional.
The blur-to-sharp adds perceived quality.
prefers-reduced-motion disables for accessibility. */
@keyframes enter {
from {
opacity: 0;
transform: translateY(24px);
filter: blur(6px);
}
to {
opacity: 1;
transform: translateY(0);
filter: blur(0);
}
}
.animate-in {
animation: enter 0.7s cubic-bezier(0.16, 1, 0.3, 1) both;
}
.animate-in:nth-child(1) { animation-delay: 0.05s; }
.animate-in:nth-child(2) { animation-delay: 0.15s; }
.animate-in:nth-child(3) { animation-delay: 0.25s; }
.animate-in:nth-child(4) { animation-delay: 0.35s; }
@media (prefers-reduced-motion: reduce) {
.animate-in {
animation: none;
opacity: 1;
transform: none;
filter: none;
}
}
/* Universal interactive transition */
a, button, [role="button"], input, select, textarea {
transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1);
}
✓ 品質ゲート:ビルド
フェーズ 4 に進む前に、以下を確認してください。
- グローバルトークンがデフォルト値ではなく、抽出値から設定されている
- レイアウトの骨組みが参照画像のセクション構成と一致している
- タイポグラフィのすべてのプロパティに明示的な値が指定されている(ブラウザーのデフォルト値を使用していない)
- コンポーネントの角丸、ボーダー、シャドウ、パディングが抽出シートと一致している
- 要素間のスペーシングが参照画像と照らし合わせて確認されている
- 参照画像にある場合にのみ、雰囲気を演出する効果が使われている
- レスポンシブ時の折り返しが実装されている
- すべてのインタラクティブ要素にホバー/フォーカス状態がある
フェーズ 4:ビジュアル差分
実装を参照画像と比較してください。これが最終確認です。以下の各カテゴリーを確認し、各項目に合格または不合格を記入してください。不合格が1つでもある場合は、納品できません。
レイアウトの差分
| 確認項目 | 合格/不合格 |
|---|---|
| セクション数と順序が一致している | |
| コンテナーの最大幅の比率が一致している | |
| 水平方向のパディングが一致している | |
| グリッドの列数と比率が一致している | |
| セクションの高さの比率が適切である | |
| セクション間の垂直方向のスペーシングが一致している | |
| セクションごとの要素の配置(左/中央/右)が一致している | |
| Z 軸方向の重なり順が一致している(該当する場合) |
タイポグラフィの差分
| 確認項目 | 合格/不合格 |
|---|---|
| フォントファミリーが読み込まれ、正しくレンダリングされている | |
| 見出しのサイズがビューポートに対して適切な比率である | |
| 見出しの太さが一致している(細すぎず、太すぎない) | |
| 見出しの行の高さが一致している(詰まっているか、ゆったりしているか) | |
| 見出しの文字間隔が一致している(狭いか、広いか) | |
| 本文の文字サイズが一致している | |
| 本文の行の高さと最大幅が一致している | |
| アイブロウ/ラベルのスタイル(サイズ、大文字・小文字、字間、フォント)が一致している | |
| 要素の種類ごとにテキストの色が一致している |
色の差分
| 確認項目 | 合格/不合格 |
|---|---|
| メインの背景色が一致している(#F5F0EB であるべきところが #FFF になっていない) | |
| テキストの色(メインとサブ)が一致している | |
| アクセントカラーが一致している | |
| ボーダー/区切り線の色が一致している | |
| セクション間に予期しない色の変化がない |
コンポーネントの差分
| 確認項目 | 合格/不合格 |
|---|---|
| ボタンの角丸が一致している(ピル型/角丸/角張った形) | |
| ボタンのパディングが一致している | |
| ボタンのテキストスタイル(サイズ、太さ、大文字・小文字、字間)が一致している | |
| カードのスタイル(角丸、パディング、ボーダー、シャドウ)が一致している | |
| ナビゲーション(高さ、背景の処理、リンクのスタイル)が一致している | |
| 画像の処理(角丸、アスペクト比、object-fit)が一致している |
スペーシングの差分
| 確認項目 | 合格/不合格 |
|---|---|
| 見出しからサブテキストまでの間隔が一致している | |
| サブテキストから CTA までの間隔が一致している | |
| カード内部のパディングが一致している | |
| 要素間のグリッドの間隔が一致している | |
| セクションのパディング(上部と下部を個別に)が一致している | |
| 全体のゆとり/ネガティブスペースが適切である |
雰囲気の差分
| 確認項目 | 合格/不合格 |
|---|---|
| 背景の雰囲気が一致している(フラット/粒子/グラデーション/光彩) | |
| シャドウの有無と強さが一致している | |
| 参照画像にある箇所で、すりガラス/ぼかし効果が使われている | |
| 参照画像にない雰囲気を演出する効果が追加されていない |
技術的な確認
| 確認項目 | 合格/不合格 |
|---|---|
| コンソールエラーがゼロである | |
| すべてのフォントが読み込まれている(FOUT/FOIT がない) | |
| すべての画像が読み込まれている(壊れたプレースホルダーがない) | |
| どのビューポートでも水平方向にはみ出さない | |
| すべてのインタラクティブ要素にホバー状態がある | |
| キーボード操作用のフォーカス可視状態がある | |
min-h-[100dvh] を使用しており、h-screen を使用していない | |
prefers-reduced-motion に対応している |
アート素材(写真、イラスト、テクスチャ)の扱い
CSS では、レイアウト、タイポグラフィ、色、幾何学的な形状を再現できます。一方、写真、手描きのイラスト、有機的な筆跡、大理石のテクスチャ、絵画風の効果は再現できません。これらが参照画像と出力のずれを生む最大の原因です。
→ 参考画像の視覚要素をすべて分類する
参考画像を確認し、各視覚要素にタグを付けます。
| 要素の種類 | CSS で再現できますか? | 代わりに行うこと |
|---|---|---|
| 単色のブロック | ✅ はい | 抽出した正確な HEX 値を使用します |
| 線形/放射状グラデーション | ✅ はい | 方向、カラーストップ、色を合わせます |
| 幾何学的な図形(円、長方形、線) | ✅ はい | CSS の図形またはシンプルな SVG を使用します |
| アイコン(アウトライン/塗りつぶし) | ✅ はい | アイコンライブラリまたはインライン SVG を使用します |
| 写真 | ❌ いいえ | 雰囲気を合わせた画像を生成するか、picsum.photos/seed/{keyword}/{w}/{h} を使用します |
| 手描きのイラスト | ❌ いいえ | generate_image ツールで雰囲気を合わせたイラストを生成します |
| 有機的なブラシストローク/ペイントテクスチャ | ❌ いいえ | 画像アセットとして生成します。CSS グラデーションで近似してはいけません |
| 大理石/流体/有機的なテクスチャ | ❌ いいえ | 画像アセットとして生成するか、高品質なストック素材を使用します |
| 3D レンダリング | ❌ いいえ | 似たレンダリングを生成するか、照明や角度が近いプレースホルダーを使用します |
| 抽象アート/ミクストメディア | ❌ いいえ | 正確なスタイル、色、構図を説明して generate_image で生成します |
→ 参考画像に写真が含まれる場合
- 第一候補: 参考画像の雰囲気、カラーパレット、被写体、構図に合った写真を
generate_imageで作成します - 第二候補: 内容に合ったキーワードを使って
picsum.photos/seed/{descriptive-keyword}/{w}/{h}を使用します(例:海の画像ならpicsum.photos/seed/ocean-waves/800/600) - 禁止事項: 写真の代わりに CSS グラデーション、ストライプ模様、単色ブロックを使用してはいけません。これは見た目の差異が最も目立つ原因です
→ 参考画像にイラストやブラシストロークが含まれる場合
- 第一候補: イラストのスタイル、色、線の質感、構図を詳しく説明したプロンプトを指定して
generate_imageを使用します。雰囲気も含めます:「白い背景を斜めに横切る、質感が目に見える有機的な手描きのピンクのブラシストローク。コーラル/ホットピンク色で、表現豊かな抽象アートに似たもの」 - 第二候補:
generate_imageを利用できない場合は、スタイルと色が合うストックイラストを探します - 禁止事項: 有機的な手描きアートを CSS グラデーションや幾何学的な図形で近似してはいけません。斜めの CSS グラデーションはブラシストロークではありません。CSS の
border-radiusで作った塊は有機的な形ではありません。違いは一目でわかります
→ テクスチャのある表面が参考画像に含まれる場合
大理石、木目、コンクリート、布、水、雲などには、実際の画像アセットが必要です。
- 特定の表面を説明して
generate_imageでテクスチャを生成します - 適切な
background-size、object-fit、位置を指定し、background-imageとして適用します - スケールを合わせます。拡大した大理石のテクスチャは、縮小したものとは見え方が異なります
→ アセットのサイズと配置
生成した画像アセットをレイアウトに配置する際は、次の点に注意してください。
/* BLUEPRINT: Image asset inside a card or container
WHY: object-fit:cover ensures the image fills the space
without distortion. object-position lets you align the
focal point of the image to match the reference. */
.asset-container {
position: relative;
overflow: hidden;
border-radius: var(--radius-card); /* match card radius */
}
.asset-image {
width: 100%;
height: 100%;
object-fit: cover;
object-position: center; /* adjust to match reference focal point */
}
⚠ 再現のずれに関する警告: これは最もよくある再現の失敗です。AI が芸術的な要素を再現できない場合、CSS のパターン(ストライプ、グラデーション、単色のブロック)で代用します。幾何学的な CSS パターンは写真や手描きアートと根本的に視覚的な質が異なるため、必ず違和感が生じます。必ず画像アセットを生成してください。不完全な生成画像であっても、CSS による近似より参考画像に近づきます。
例外的なケース
フォントを特定できない場合
- 有力な候補を 2~3 個挙げ、どの文字の特徴からそれぞれが候補になるのかを説明します
- DevTools → Computed Styles →
font-familyを確認して、公開中のサイトを調べるようユーザーに提案します - 最も近い Google Font をデフォルトとして使用します
--font-display変数を 1 か所変更するだけでフォントを差し替えられるように CSS を構成します
参照画像の解像度が低い場合
- 確実に判断できる要素(レイアウト、配色、全体的なタイポグラフィ)を抽出します
- 不確かな寸法は明示します
- より高解像度の画像、または公開中のサイトの URL を求めます
- ぼやけたスクリーンショットから、サブピクセル単位の詳細を推測してはいけません
参照画像に再現できないコンテンツが含まれている場合
参照画像には、ライブチャット、実際のユーザーアバター、リアルタイムデータなどの動的コンテンツが含まれていることがあります。
- 静的なプレースホルダーデータを使って、見た目を再現します
- 現実味のあるコンテンツを使います。「John Doe」や「99.99%」のようなものではなく、実在しそうな名前や自然な数値を使います
- 納品物のどの要素がプレースホルダーなのかを記載します
芸術的なコンテンツ(写真、イラスト、テクスチャ)については、上記の「芸術的アセットの扱い」セクションを参照してください。CSS で近似してはいけません。必ず実際の画像を生成するか、用意してください。
複数の参照画像が提供されている場合
- 各画像について、完全な抽出作業を個別に行います
- 画像間でデザインシステム(フォント、色、コンポーネント)が一貫していることを確認します
- 不一致がある場合は、どの画像を基準とするかユーザーに尋ねます
- デスクトップとモバイルのペアでは、デスクトップ画像をデザインシステムに、モバイル画像をレスポンシブブレークポイントの確認に使います
参照画像に見覚えのあるコンポーネントライブラリが使われている場合
shadcn/ui、Radix、Material などのライブラリを見つけた場合:
- どのライブラリが使われていると思うかを伝えます
- ライブラリを使うか、手動で再現するかを尋ねます
- ライブラリを使う場合:適切にインストールし、見た目が一致するようテーマを設定します
- 手動で再現する場合:依存関係を追加せずに、見た目を一致させます
基本原則
参照画像が仕様です。コードは翻訳です。あなたはデザイナーではなく翻訳者です。自分の好みではなく、画像に合わせてください。参照画像があなたの美的感覚と食い違う場合は、参照画像を優先します。許される唯一の技術的な例外は、
h-screenがデザイン上の選択ではなくブラウザーの不具合であるため、h-screenの代わりにmin-h-[100dvh]を使うことです。