動画で読む
まず結論 — AI の UI が「それっぽい」止まりなのは、値だけ渡しているから
結論から書きます。AI コーディングエージェント(コードを自律生成する AI ツール)が吐く UI が「いかにも生成」に見えるのは、色や余白の値だけを渡して、その値を「いつ・なぜ使うか」を渡していないからです。#0066CC という 1 行は、リンクの色なのか、ボタンの色なのか、フォーカスリングの色なのかをエージェントに教えてくれません。判断材料が無いまま、エージェントは無難な真ん中を選びます。だから余白も配色もバラつき、平均的な見た目に着地する。
きっかけは Zenn の「DESIGN.md」記事(53able) でした。著者は、色・間隔・形状の値そのものより「なぜそう見せるのか」を Markdown で先に固定し、エージェントに毎回それを参照させる運用を提案しています。私はこれを、自分が AetherEchoes で組んだデザイントークン(色や余白などを名前付きで管理する仕組み)体系と引き比べながら読み、「値より役割を先に書く」という一点は確かに効く、と腑に落ちました。
なぜ token の「値」だけでは足りないのか
トークンは値の名簿ではなく、判断の辞書であるべきです。--accent: #E63946 と書くだけでは、エージェントはその赤を見出しの下線に使ってよいのか、エラー表示に取っておくべきなのか分かりません。
少し前、Cursor に「クリーンなカードを並べて」と頼んだことがあります。出てきたのは、padding が 16px のカードと 20px のカードが混在し、影の強さも 3 段階にバラついた一覧でした。動いてはいる。けれど「クリーン」という言葉が値に翻訳される過程で、エージェントは毎回その場の最適解を選び直していたわけです。指示が抽象語だと、生成のたびに別の解釈が混ざる。これは AI が悪いのではなく、判断の前提を渡していない私の問題でした。この構図は、AI 生成コードを静的スキャンで検証する話 で書いた「動いた、は安全の証明ではない」とよく似ています。動く出力ほど、前提の不在が見えにくい。
DESIGN.md に書く 3 つ — token / 余白スケール / コンポーネント語彙
DESIGN.md に固定すべきは、値そのものではなく「値 + 役割 + 避けるべきパターン」の三点セットです。書く順番にも意味があります。
- token に役割を添える:
{colors.primary}のような参照名で機械的に扱えるようにしつつ、各値の隣に「リンクと CTA に使う / フォーカスリングには使わない」と一文を書く。値だけの名簿にしない。 - 余白スケールを段階で固定する: 4 / 8 / 12 / 16 / 24 のように刻みを決め、「カード内は 16、セクション間は 24」と用途を縛る。これだけで、さっきの 16px と 20px が混ざる事故は消えます。
- コンポーネント語彙を Do / Don't で書く: 「premium」「modern」のような形容詞で終わらせず、「角丸は 8px 固定、影は 1 段階だけ、ホバーで影を足さない」と具体に落とす。避けるべきパターンを明記するほど、生成のブレ幅は狭まる。
Zenn の記事も「抽象語だけで終わらせない」点を一番強く押していて、ここは私の実感と一致しました。実装の見た目を「意図どおり」に寄せる話としては、ピクセルパーフェクトを意図の一致として捉え直す話 とも地続きです。
AetherEchoes の実例 — --ink は「本文・主役」、--cat-color は data-cat で解決
私のサイトでは、2026 年 5 月に採択したトークン体系で、値に必ず役割コメントを添えています。たとえば --ink: #0E0E0E には「本文・主役テキスト」、--ink-muted: #6E6E6A には「キャプション・メタ」と書いてある。色を選ぶ側(人でもエージェントでも)は、16 進の数字ではなく --ink-muted という名前で「これはメタ情報の色だ」と判断できます。
部門カラーはもう一歩進めて、5 部門の色を --cat-engineering などで定義しつつ、ページ側は data-cat="design" という属性から --cat-color を解決する形にしています。
--cat-design: #FFB020;
[data-cat="design"] { --cat-color: var(--cat-design); }
こうしておくと、記事ページのヒーロー番号・引用罫・目次のアクティブ色は全部 --cat-color を見るだけでよく、「この記事は design だからオレンジ」という判断をコンポーネント側が持たなくて済みます。値を直接書かせない、役割名だけを参照させる。DESIGN.md の思想を、CSS 変数の解決順でも体現しているわけです。配色の一貫性を別角度から詰めたコントラスト検証を要素×状態×テーマで総当たりする話 とも、根は同じ「状態を取りこぼさない」発想だと思っています。
運用に落とす — DESIGN.md と実装テーマを同じ PR で動かす
DESIGN.md は、作っただけだとすぐ実装と乖離します。だから私は、トークンの値を変えるときは DESIGN.md・Tailwind の @theme・CSS 変数を必ず同じ PR でまとめて触る、というルールにしています。
ドキュメントとコードが別 PR で進むと、片方だけ更新されて「DESIGN.md には残っているのに実装には無い色」が生まれる。これは半年後の自分が一番ハマる罠です。実際、過去の私が書いた token が実装のどこを探しても見つからず、30 分溶かしたことがあります。役割を書いた DESIGN.md は、AI に渡す前提であると同時に、人間のレビュー観点表でもある。ちなみにこの AetherEchoes 自体、記事は AI が下書きを書き、私が公開前に確認・編集して出していて、文章でもコードでも「AI が起稿し、人間が検証して通す」構図は同じです。設計を言葉で先に固定するほど、生成は速くなり、レビューは楽になる。
よくある質問
- DESIGN.md と AGENTS.md や README は何が違うのですか?
- READMEは人間向けの概要、AGENTS.mdはエージェント向けの作業手順、DESIGN.mdはエージェント向けの「視覚判断の根拠」を担います。同じトークンでも、値だけでなく役割と避けるべきパターンを書く点がDESIGN.mdの役割です。
- トークンに値だけ書くと、なぜAIのUIがばらつくのですか?
- 値だけではAIがその色や余白をどの場面で使うべきか判断できず、生成のたびに無難な解釈を選び直すからです。役割と用途を添えると判断の前提が固定され、padding16pxと20pxが混在するようなブレが減ります。
- DESIGN.mdと実装の乖離はどう防げばよいですか?
- トークンの値を変えるときは、DESIGN.mdとTailwindのテーマ、CSS変数を必ず同じPRでまとめて触るのが有効です。別PRで進めると片方だけ更新され、ドキュメントにしか存在しない色が生まれて後で混乱します。