design toolsMay 3, 202613 min read

Figma Variables アーキテクチャ:本番で生き残るトークンシステムの作り方

Figma variables の実践的アーキテクチャガイド。3層トークンモデル、モードとコレクションの判断基準、そしてシステムの半分を書き直すことなく variables を Figma からコードへ持ち出すハンドオフのパターンを解説します。

By Boone
XLinkedIn
figma variables architecture

Figma Variables アーキテクチャ:本番で生き残るトークンシステムの作り方

Figma variables を使っているチームの多くは、スタイルのメンタルモデルの上に構築している。そして、それこそが問題だ。アーキテクチャのない variables は、クリック数が増えただけのスタイルにすぎない。

うまくいっているチームは、Figma variables を本物のデザイントークンレイヤーとして扱っている。構造化され、エイリアスされ、スコープが決まり、エクスポートできる。うまくいっていないチームは、ダークモードの要望が1つ来ただけで全面的な作り直しになる。これが、本番で生き残るアーキテクチャだ。

Variables はスタイルではない、トークンレイヤーだ

Figma のスタイルはプリセットだ。色、テキストスタイル、エフェクトを定義して、レイヤーに直接適用する。単一ブランド、単一モードで、開発ハンドオフの要件がないファイルならそれで足りる。でも何かが変わった瞬間に破綻する。

Figma variables はトークンだ。variable は値を持てるが、別の variable への参照も持てる。その参照チェーンと、モードによって解決済みの値のセットをまるごと切り替えられる仕組みこそが、variables をスタイルとアーキテクチャ的に別物にしている。この違いは見た目の話ではない。プリセットシステムとトークンシステムの違いだ。

3層トークンアーキテクチャ

プリミティブ、セマンティック、コンポーネント。機能する variable システムには必ずこの3層がある。セマンティックレイヤーを飛ばすのは、今の Figma ファイルで最も多いアーキテクチャ上のミスだ。

3層は3つの役割に対応する。プリミティブは生の値を持ち、セマンティックトークンは意味を担い、コンポーネントトークンは1つのコンポーネントファミリーにスコープされる。各レイヤーは直下のレイヤーとだけ話す。飛ばさない、近道もしない。

レイヤー持つもの参照先例
プリミティブ生の値なしblue-500: #0066FF
セマンティック意味プリミティブのみtext-link: blue-500
コンポーネントコンポーネントの状態セマンティックトークンbutton-text: text-link

3層はプロジェクト規模によって省略できるものではない。コンポーネントが5つしかない小さなシステムでも3層すべてが必要だ。さもないと最初のテーマ変更の要望で吹き飛ぶ。

レイヤー1:プリミティブ

プリミティブは生の値だ。blue-500、gray-900、space-4、radius-md。パレットであり、スケールであり、土台だ。コンポーネントレイヤーに直接付けてはいけない。

プリミティブの仕事は、存在すること、上からエイリアスされること、そして邪魔をしないことだ。デザイナーがボタンに blue-500 を当てようとしているなら、アーキテクチャはすでに壊れている。プリミティブはプリミティブのコレクションにだけ置く。

ここでは命名規則が重要になる。プリミティブはスケールベースかパレットベースにして、セマンティックにしてはいけない。blue-500 は正しい。プリミティブとしての button-blue はカテゴリーエラーで、規模が大きくなると痛い目を見る。

レイヤー2:セマンティック

セマンティックトークンは意味を担う。surface、surface-elevated、text-primary、text-muted、border-default、border-focus。「これは何色か?」ではなく「この色は何のためか?」に答える。

セマンティックトークンはプリミティブにエイリアスする。持つ関係はそれだけだ。セマンティックからセマンティックへのエイリアスは、値がどこにあるのかを曖昧にし、モードのオーバーライドを信頼できなくする。

このレイヤーに、ライト、ダーク、ブランドのモードが住む。セマンティックトークンは、アクティブなモードに応じて別のプリミティブに解決される。テーマ切り替えは実際こうして動く。プリミティブ blue-500 は変わらない。セマンティックトークン text-link が、モードに応じて解決先を変えるのだ。

レイヤー3:コンポーネント

コンポーネントトークンは1つのコンポーネントファミリーにスコープされる。button-bg、button-text、button-border、card-surface、card-border、input-bg。セマンティックトークンにエイリアスし、プリミティブには決してエイリアスしない。

コンポーネントトークンの役割は、結合なしの特異性だ。button-bg は surface-action に解決され、それが blue-500 に解決される。ブランドが変わったらセマンティックレイヤーを更新すれば、ボタンも一緒に更新される。コンポーネントトークンには触らない。

よくある反論は、「理由もなくトークンが増えるだけに感じる」というものだ。理由は、button-bg と surface-action が分岐しうるからだ。いつか、プロダクトの判断でボタンだけ少し違うサーフェスを使うことになる。コンポーネントトークンがあれば、セマンティックシステムに触れずにオーバーライドのポイントを確保できる。

モード対コレクション:判断ツリー

モードはコレクション内の値を切り替える。コレクションは関心事を分離する。この2つは同じではなく、混同することが Figma variable 設計における混乱のほとんどの原因だ。

ルールはこうだ。関心事ごとに1コレクション、同じ関心事のバリエーションにはモード。色は1つの関心事。スペーシングも1つの関心事。ライトとダークは別々の関心事ではない。同じ色という関心事のモードだ。

モードを使うか、新しいコレクションにするか:

  • 同じものの別の値? モード。
  • まったく別のもの? コレクション。
  • ライトとダークの切り替え? カラーコレクション内のモード。
  • コンパクトとコンフォートなスペーシングの切り替え? スペーシングコレクション内のモード。
  • ブランドの追加? セマンティックレイヤー内のモードであり、新しいコレクションではない。
シナリオ間違ったやり方正しいやり方
ライト / ダークカラーコレクションを2つ作る1つのカラーコレクションに2つのモード
ブランドA / ブランドBセマンティックコレクションを2つ作るセマンティックコレクションに2つのブランドモード
コンパクト / デフォルトのスペーシングカラーコレクションに混在させるスペーシングコレクション内のモード
英語 / アラビア語(RTL)別の variable ファイルロケールモード付きの文字列 variables

4つのスコープルール

variable のスコープは、Figma のどこにその variable を適用できるかを制御する。ここを間違えると、デザイナーがセマンティックトークンではなくプリミティブに手を伸ばしてしまい、アーキテクチャの規律は使う場面で崩れる。

4つのルールに交渉の余地はない。

  1. プリミティブのスコープは none にする。 プリミティブはどこにも適用できてはいけない。内部の値であって、利用者向けのトークンではない。適用ドロップダウンから完全に隠す。
  2. セマンティックトークンは自分の型にスコープする。 カラーのセマンティックトークンは fill と stroke にスコープする。スペーシングトークンは gap、padding、size の各フィールドにスコープする。スコープは狭く保つ。
  3. コンポーネントトークンは自分のファミリーにスコープする。 ボタンのトークンをカードに適用できてはいけない。スコープが広すぎると、コンポーネントの境界は意味を失う。
  4. プリミティブを利用者に決して公開しない。 デザイナーや開発者がプリミティブをレイヤーに適用しているなら、システムはスコープのレイヤーで失敗している。これはプロセスの失敗であり、ユーザーの失敗ではない。

テーマを可能にするエイリアスチェーン

機能するテーマはエイリアスの連鎖だ。コンポーネントがセマンティックにエイリアスし、セマンティックがプリミティブにエイリアスし、プリミティブが値を持つ。チェーンの長さは3。常に3だ。

長さ2のチェーン(コンポーネントからプリミティブ)は翻訳レイヤーを飛ばすので、すべてのコンポーネントトークンに手動オーバーライドをしない限りモードが成立しない。長さ4のチェーンは、どのセマンティックレイヤーがモードを担うのかを曖昧にし、監査は参照ではなくデバッグ作業になる。

button-bg → surface-action → blue-500 → #0066FF

このチェーンは、セマンティックコレクションのダークモードで surface-action が blue-300 を指すよう更新するだけでダークモードを乗り切る。button-bg トークンは自動で更新される。プリミティブ blue-500 は引き続き #0066FF に解決される。ほかには何も変える必要がない。

3層のエイリアスチェーンを示すボクセルのコンセプト画像:コンポーネントトークンがセマンティックトークンを指し、それがプリミティブの値を指す。コンポーネントトークンに触れずにテーマ切り替えが伝播する様子を表している
3層のエイリアスチェーンを示すボクセルのコンセプト画像:コンポーネントトークンがセマンティックトークンを指し、それがプリミティブの値を指す。コンポーネントトークンに触れずにテーマ切り替えが伝播する様子を表している

ライト、ダーク、ブランドのモード

ほとんどの variable システムに必要なモードは、ライト、ダーク、ブランドの3つ。これらを担うのはセマンティックレイヤーだけだ。プリミティブレイヤーでは決してない。

プリミティブにモードを適用するのはカテゴリーエラーだ。blue-500 は常に #0066FF である。プリミティブだからだ。意味を持たないので、ライトやダークのバリエーションはない。セマンティックトークン text-link にライトとダークのバリエーションがあるのは、文脈によって解決が変わる意味を担っているからだ。

ブランドモードも同じ仕組みだ。2つ目のブランドが本当に異なる生の値を使うのでない限り、2つ目のプリミティブパレットは要らない。たいていは、セマンティックレイヤーのブランドモードが既存プリミティブの別のサブセットを指すのが正解だ。2つのブランドに完全なプリミティブコレクションを2つ用意するのは、たいてい作り込みすぎだ。上流の色の判断がこれをどう形作るかについては、セマンティックレイヤーの構造を固める前にダークモードのカラーシステムの記事を読んでおく価値がある。

Number、String、Boolean の variables

Figma variables は色だけではない。Number variables はスペーシング、サイズ、角丸を制御する。String variables はデザインファイル内のコピーを制御する。Boolean variables はレイヤーの表示を制御し、これはコンポーネントの props に直接対応する。

ここは、ほとんどのチームが使っていない variables システムの領域であり、デザインとコードのギャップを最も劇的に埋める部分でもある。number variables で定義したスペーシングスケールを auto-layout の gap に適用すれば、variable のスペーシングを変えるだけで、そのトークンを使うすべてのコンポーネントが更新される。それが本物のトークンシステムのやることだ。

ロケールモード付きの String variables を使えば、デザイナーはファイルを英語とアラビア語で切り替え、レイアウトが崩れる様子をリアルタイムで確認できる。コンポーネントの props に対応する Boolean variables があれば、Figma のコンポーネントとコードのコンポーネントが props で一対一の関係になり、開発ハンドオフは解釈ではなくレビューできるものになる。

コードへのハンドオフ:うまくいくパターン

variable システムの価値は、そのエクスポートで決まる。機能するハンドオフのパターンは、Tokens Studio または Figma Variables REST API に、変換パイプラインと、コード側のインポートスクリプトを組み合わせたものだ。

Tokens Studio はvariable コレクションを、Style Dictionary と互換性のある構造化 JSON 形式にエクスポートする。Style Dictionary はその JSON を、コードベースが必要とするあらゆる出力に変換する。CSS カスタムプロパティ、Swift のカラーセット、Kotlin のリソースファイル、Tailwind の設定などだ。変換のステップで命名規則が正規化され、コードの慣習に合わない Figma 固有の命名が整理される。

パイプラインは手動ではなく、variable を更新するたびに走らせるべきだ。Tokens Studio の push で起動する GitHub Action や、variable の変更で発火する Figma の webhook を使えば、誰もエクスポートを覚えていなくてもコード側のトークンは同期され続ける。これは Stripe や Atlassian が大規模に運用しているパターンで、ビルドステップのあるコードベースならどこでも実現できる。その出力におけるカラートークンのフォーマットの判断については、CSS カスタムプロパティの値を固める前にOKLCH colorを読んでおく価値がある。


モード、ブランド、開発ハンドオフを書き直しなしで乗り切る Figma variable システムが欲しいなら、Brainy が3層モデル、エイリアスチェーン、そしてコードベースにすんなり収まるエクスポートパイプラインを備えた、本番品質のトークンアーキテクチャを Figma で設計します。Brainy に依頼する


variable システムを壊す7つのよくあるミス

#ミス何が壊れるか
1セマンティックからセマンティックへのエイリアスモードの解決が予測できなくなる
2プリミティブを利用者に公開デザイナーがセマンティックレイヤーを迂回する
3ブランドを別コレクションで扱いモードを使わないテーマ切り替えが手作業の検索置換になる
4コンポーネントトークンがプリミティブにエイリアスダークモードのたびにすべてのコンポーネントトークンの更新が必要になる
5どの variable にもスコープを設定しないシステムが強制力を失い、使う場面で崩壊する
6スペーシングと色を1つのコレクションに混在モードのオーバーライドが関心事をまたいで漏れ出す
7意味を持たない variable 名コードへのハンドオフに翻訳辞書が必要になる

これらのミスの多くは根っこが同じだ。variables パネルを、アーキテクチャのレイヤーではなく、ちょっと良くなったスタイルパネルとして扱っていること。メンタルモデルを切り替えることが解決策であり、あとはすべてそこから導かれる。

variable システム監査

どんな Figma variable システムでもこの監査を実行すれば、出荷前にアーキテクチャの負債を見つけられる。

構造

  • 最低3つのコレクション:プリミティブ、セマンティック、コンポーネント(または同等の命名)
  • 各コレクションが明確な単一の関心事を持つ
  • 型が混在するコレクションがない(色とスペーシングを同じコレクションに入れるのは失敗)

エイリアスチェーン

  • すべてのコンポーネントトークンが、プリミティブではなくセマンティックトークンにエイリアスしている
  • すべてのセマンティックトークンが、別のセマンティックトークンではなくプリミティブにエイリアスしている
  • プリミティブ以外に生の値を持つトークンがない
  • すべてのカラートークンでエイリアスチェーンの長さがちょうど3

モード

  • ライトとダークは別コレクションではなく、セマンティックコレクション内のモードである
  • ブランドのバリアントは別ファイルではなく、セマンティックコレクション内のモードである
  • プリミティブコレクションにモードがない

スコープ

  • プリミティブ variables のスコープが none(どこにも適用できない)
  • セマンティック variables が自分の型にスコープされている(色は fill/stroke、スペーシングはレイアウトのフィールド)
  • コンポーネント variables が自分のコンポーネントファミリーにスコープされている

ハンドオフ

  • variables を Tokens Studio または REST API でエクスポートできる
  • 変換パイプラインが存在し、自動化されている
  • コード側のトークンが、文書化された例外を除き Figma の variable 命名規則と一致している

3つを超える項目が失敗したら、そのシステムにはパッチではなく作り直しが必要だ。監査で最も負債が見つかったのがプリミティブレイヤーなら、そこに流れ込む上流の色の判断についてはブランドカラーパレットが参考になる。

FAQ

Figma variables と Figma styles の違いは何ですか?

スタイルはレイヤーに直接適用するプリセットだ。variables は互いに参照でき、モードで値を切り替えられるトークンだ。variables はスタイルができることをすべてでき、さらにテーマ化と、エクスポートによる開発ハンドオフもできる。新しいデザインシステムなら、variables が正しい選択だ。成熟したスタイルシステムを持つ既存ファイルでは、切り替える前に移行計画を書いておく価値がある。

Figma variable システムにはコレクションをいくつ持たせるべきですか?

ほとんどのシステムで3から5つだ。プリミティブ、セマンティック、コンポーネント、そしてスケールが複雑で独自のスコープルールが必要なら、スペーシングとタイポグラフィの別コレクションを加える。コレクションが5つを超えるなら、たいてい関心事が正しくグルーピングされていないサインだ。

Figma variables は Tokens Studio の代わりになりますか?

Figma 内での作成と編集なら、なる。ネイティブの variables パネルは、variables API が出る前に Tokens Studio がやっていたことのほとんどをこなす。エクスポートと変換では、Tokens Studio がまだ価値を発揮する。Style Dictionary への成熟したパイプラインがあり、ネイティブのエクスポートが扱えないエッジケースにも対応しているからだ。今のところ、この2つのツールは競合ではなく補完関係にある。

セマンティックトークンを別のセマンティックトークンにエイリアスするとどうなりますか?

モードの解決が曖昧になる。text-secondary が text-primary にエイリアスしていてダークモードに切り替えると、Figma はチェーンを解決するが、期待した場所にダークモードのオーバーライドが適用されないことがある。セマンティックからセマンティックへのエイリアスは、規模が大きくなるとシステムの監査もほぼ不可能にする。ルールは厳格だ。セマンティックトークンはプリミティブにだけエイリアスする。

システムを作り直さずに3つ目のブランドを扱うには?

セマンティックコレクションに3つ目のモードを追加する。ブランドが本当に異なる生の値を使わない限り、プリミティブコレクションはブランド間で共有する。セマンティックレイヤーのブランドモードが、プリミティブの別のサブセットを指すのが正しいアーキテクチャだ。ブランドがあまりに違ってプリミティブのパレットが重ならない場合は、セマンティック構造を共有したままプリミティブコレクションを2つ持つのが次善策になる。

小さなプロジェクトでも3層モデルは必要ですか?

必要だ。ただし各レイヤーの大きさは小さくなる。小さなプロジェクトなら、プリミティブが15個、セマンティックトークンが8個、コンポーネントごとにコンポーネントトークンが2個、といった具合だろう。それでもアーキテクチャは3層だ。小さなプロジェクトでセマンティックを飛ばしたくなる誘惑こそが、2人目のデザイナーやダークモードの要望が現れた瞬間に、多くの小さなプロジェクトがアーキテクチャの負債になる理由だ。トークンアーキテクチャがより広い技術スタックの判断のどこに位置づくかについては、Framer vs Webflow vs Next.jsの記事に文脈がある。

Figma variables が本当に解き放つ変化

Figma の本物の variable システムは、デザイン側と開発側が「信頼できる唯一の情報源」に最も近づいた形だ。ハンドオフのドキュメントではない。Zeplin のリンクでもない。両側が同じ定義から読み取る、生きていて、エクスポート可能で、構造化されたトークンレイヤーだ。

variables をアーキテクチャとして扱っているチームは、デザインシステムの負債を半分に減らしている。variables が魔法だからではない。良い variable システムが求めるアーキテクチャの規律が、デザインシステムが先送りし続けてきた判断を強制するからだ。このトークンは何を意味するのか? 何にエイリアスできるのか? プリミティブは誰のものか? これらの問いには今や答えがあり、その答えはファイルの中にある。

アーキテクチャのない variables は、クリック数が増えただけのスタイルにすぎない。3層モデル、エイリアスチェーン、スコープルール、エクスポートパイプラインを備えた variables は、2つ目のブランドも、ダークモードも、Figma を一度も開いたことのない開発者も乗り切れるデザインシステムだ。

トークンだけでなく、アーキテクチャを作ろう。

Want a Figma variable system that survives modes, brands, and dev handoff without rewrites? Brainy designs production token architectures in Figma with the three-layer model, the alias chain, and the export pipeline that drops cleanly into your codebase.

Get Started

More from Brainy Papers

Keep reading