この記事で分かること
- AI にデザイン実装を任せるとき、なぜ「スクリーンショットでの見た目確認」が破綻するのか
- 画像比較(ピクセル差分・知覚ハッシュ)ではなく、Figma から抜いた正解値との数値比較で合否を出す設計
- Claude Code のスキル + サブエージェントで、取得 → 実装 → 検証のループをどう組んだか
きっかけ:AI には「視覚」がないので、実装の合否を自分で判断できない
Figma のデザインをコードに起こす作業は、AI にとって「変換」自体は得意でも、「出来上がった画面がデザイン通りか」の判定が鬼門です。人間なら見れば分かりますが、AI に「スクリーンショットを見て合ってる?」と聞くと、モデルや実行のたびに答えがブレます。
この課題に対して「Figma とブラウザ表示を比較する MCP を作る」というアプローチ(参考記事)があります。画像を知覚ハッシュやピクセル差分で突き合わせる方法です。
私は別の方向で解きました。そもそも画像を比較しない、というものです。
設計の核心:「見た目」ではなく「数値」で合否を出す
考え方はシンプルです。
- Figma から各要素の正解値(フォントサイズ・行間・色・余白・角丸など)を数値として抜き出し、
values.jsonに保存する - 実装したコンポーネントをブラウザでレンダリングし、
getComputedStyleで実測値を取る - 正解値と実測値をスクリプトで機械的に数値比較する(LLM に判断させない・ピクセルも見ない)
この比較を通すことを「完了」の定義にしました。「たぶん合ってる」ではなく「数値が一致した」で判定するので、**モデルが変わっても実行するたびに結果が同じ(決定的)**になります。
なぜ画像比較を採らなかったか
- ピクセル/知覚ハッシュ比較は、フォントレンダリングの微差やアンチエイリアスで偽陽性が出やすく、「どこがどれだけズレたか」を数値で言えない
- LLM に見た目を判断させるのは非決定的で、そもそも今回避けたい当のもの
数値比較なら「fontSize が期待 18px・実測 16px」のように原因がそのまま出るので、修正ループとの相性が段違いです。
検証スクリプトのイメージ
比較ロジックはブラウザ非依存の純粋関数にして、単体で確かめられるようにしています(色は oklch → sRGB に正規化、行間は「比率 × フォントサイズ」で換算、など Tailwind v4 特有の差も吸収)。
// 正解値(values.json)と getComputedStyle の実測値を比較する例
export function compareValue(prop, expected, actual, ctx = {}) {
if (prop === 'color' || prop === 'backgroundColor') {
const e = normalizeColor(expected); // #hex / rgb() / oklch() を [r,g,b,a] に正規化
const a = normalizeColor(actual);
return { pass: e.every((c, i) => Math.abs(c - a[i]) <= (i === 3 ? 0.02 : 1)) };
}
if (prop === 'lineHeight') {
// Figma は比率、CSS は px で返るので fontSize を掛けて突き合わせる
return { pass: Math.abs(Number(expected) * ctx.fontSizePx - toPx(actual)) <= 1 };
}
// 寸法系は ±1px 許容で比較
const ep = toPx(expected), ap = toPx(actual);
return { pass: Math.abs(ep - ap) <= 1 };
}
さらに Tailwind CSS v4 は存在しないクラス名を警告なく捨てるため、ビルドも型チェックもすり抜けます。これを潰すために「未定義クラス 0 件」を別スクリプトで検証し、これも合否ゲートに含めています。
成功基準 = 「数値比較が一致」+「未定義クラス 0 件」の両方を通ること。 通るまで自動で修正ループを回します。
全体のワークフロー(Step 0〜7)
「実装を開始して」の一言で、以下を順に流します。要所(★)で「次に進んでいい?」の承認を挟みます。
| Step | 内容 |
|---|---|
| 0. Figma 確認 | 対象ファイル・タイプの確定 |
| 1. トークン同期 | Figma の色・文字スタイルをコード側のデザイントークンに取り込む |
| 2. デザイン取得 | 各コンポーネントのデザイン情報を取得しキャッシュ + 正解値 values.json を生成 |
| 3. コンポーネント実装 | 5 個ずつ並行してコード化 |
| 4. レンダリング検証 | 上記の数値比較で合否判定(通るまで修正) |
| 5. ページ組み込み | コンポーネントを組み合わせて 1 ページに |
| 6. 最終検証 | ページ全体・アクセシビリティ・コード品質・セキュリティを総点検 |
| 7. コミット | 明示指示があった時だけ実行 |
スケールさせるための工夫
サブエージェントで並行実装
コンポーネントは 5 個ずつ別々のサブエージェントに割り当てて同時進行します。メインのコンテキストを汚さず、大量のコンポーネントでも破綻しにくくしています。
ゴールデンサンプル方式
最初の 1 個だけを丁寧に実装し、それを「変換のお手本」として以降のエージェントに参照させます。1 個目で変換パターンを固め、残りは効率よく量産する狙いです。
キャッシュ
一度取得した Figma のデザインデータは再利用します。「デザイン更新あった?」だけ確認し、更新がなければ取得をスキップします。
2 つの実行モード
- normal:エラーが出ても自力で対処して最後まで走る(本番実装用)
- developer:エラーで止まって原因と改善案を相談する(ワークフロー自体を鍛える検証用)
目視の役割は「補助」だけに限定した
スクリーンショットによる確認を完全になくしたわけではありません。ただし確認対象を「セクション順の誤り・要素の欠落や重なり・テキスト切れ」の 3 点だけに絞りました。色・寸法・余白の良し悪しは数値検証に委ね、目視では指摘しません。モデルによる「なんとなく気になる」の指摘ブレを構造的に排除するためです。
次の一手:位置・寸法・構造の検証(検討中)
数値比較でカバーしきれていない穴もあります。要素の幅・高さ・兄弟の並び順・flex 方向の誤りなどは、プロパティ値の比較だけではすり抜けます。
そこで冒頭の参考記事の「layout_tree(要素の座標を親相対で比較する)」の考え方を、画像比較ではなく決定的な数値比較として取り込む検証(Figma の bounding box と DOM の getBoundingClientRect を突き合わせる)を試作しました。ただし許容差やレスポンシブ時の挙動が実データでまだ検証できていないため、現状は必須ゲートには昇格させず「参考」扱いに留めています。未検証の推測値を成功基準に据えると、かえって偽陽性で作業を止めてしまうためです。
まとめ
- AI にデザイン実装を任せる鍵は、合否判定を目視から「決定的な数値比較」に移すこと
- 画像比較(ピクセル・知覚ハッシュ)や LLM の見た目判断は非決定的で、原因も特定しづらい。Figma から抜いた正解値 ×
getComputedStyleの実測値なら、原因がそのまま出て修正ループが回る - 取得 → 実装 → 検証を Claude Code のスキル + サブエージェントでオーケストレーションし、並行実装・ゴールデンサンプル・キャッシュでスケールさせた
- 「なんとなく合ってる」ではなく「数値が一致した」を完了の定義にすることで、モデルや実行に依存しない再現性を確保した
同じように「AI にデザイン実装を任せたいが品質の担保が不安」という方の参考になれば幸いです。