【テクニカル・上級編】Figmaの「Styles」と「Variables」の境界線!大規模プロジェクトにおける使い分けの基準と移行戦略 – UI/UX・デザインツール活用バイブル

Figmaの「Styles」と「Variables」の境界線:大規模デザインシステムにおけるトークン駆動アーキテクチャの極意

デザインシステムの黎明期、私たちはFigmaの「Styles(Color Styles, Text Styles等)」というプリミティブな抽象化層に救われていた。しかし、数千のコンポーネント、マルチブランド、ダークモード、そしてエンジニアリング領域のデザイン・トークン(Design Tokens)との完全な同期が求められる昨今、Styles単体での運用は限界を迎えている。

Figmaに「Variables(変数)」が導入されたことにより、私たちは真の意味で「コードとデザインのデータモデルの統一」に到達した。だが、ここで多くのプロダクトチームが混乱に陥る。
「どこまでをStylesで維持し、どこからをVariablesに移行すべきなのか?」

本稿では、UI/UXエンジニアおよびデザインシステム・アーキテクトに向けて、両者の内部アーキテクチャ、メモリフットプリント、そしてAPI/CLIを用いた完全自動化パイプラインの構築に至るまで、骨の髄までしゃぶり尽くす極限の知見を共有する。

—

1. 内部アーキテクチャと機能的境界線の解剖学

まず、Figmaのエンジン内部でStylesとVariablesがどのように処理されているかを理解する必要がある。ここを誤ると、大規模プロジェクトにおいてレンダリングパフォーマンスの劣化やメモリリークを誘発する。

Styles(スタイル)の正体

Stylesは、特定のプロパティセット(塗り、境界線、効果、タイポグラフィ)への「ポインタ(参照)」である。

  • 特性: 静的であり、コンテキスト(モードやテーマ)を持たない。
  • メモリフットプリント: 比較的軽量だが、タイポグラフィースタイルなどはFont Family、Weight、Line Heightなどの複合データを持つため、ノードツリーが巨大化するとパースコストが微増する。
  • 限界: 「Dark ModeだからこのColor Styleの参照先を自動で切り替える」といった動的なコンテキストスイッチングができない(レイヤー側でのオーバーライドやセクションごとのテーマ適用が必要)。

Variables(変数)の正体

Variablesは、プリミティブな値(Color, Number, String, Boolean)を抽象化した「トークン・ストア」であり、モード(Modes)という多次元のマトリクスを持つ。

  • 特性: 動的であり、スコープ(用途制限)とコレクション、そしてモードによる値のスイッチングが可能。
  • メモリフットプリント: コレクションとモードの組み合わせ(マトリクス)が爆発的に増加すると、Figmaのドキュメントロード時の初期化フェーズにおけるJSONパースおよびメモリ消費量に直結する。
  • 真髄: エンジニアリング側のW3C Design Tokens Format(JSON)と1:1でマッピングできる唯一のデータ構造。

—

2. 境界線の設計基準:どちらをどこに割り振るべきか?

「すべてをVariablesに置き換えればいい」という短絡的な思考は、デザインシステムのパフォーマンスとメンテナンス性を破綻させる。以下のマトリクスに基づき、厳格な境界線を引け。

| プロパティ / ユースケース | 推奨仕様 | 判断理由とアーキテクチャ上の根拠 |
| :— | :— | :— |
| カラー(背景、表面、ボーダー) | Variables | モード(Light/Dark)による動的切り替えが必須なため。Alias(参照)構造を作りやすいため。 |
| タイポグラフィ(フォント、サイズ等) | Styles | 現状のFigmaにおいて、Variablesはフォントファミリーや複合的なプロパティ(Font Weight, Line Height等)を一つの変数として束ねる「Typography Token」をネイティブサポートしていないため。(※部分的なNumber変数での制御は破綻の元) |
| スペーシング・レイアウト(Padding等) | Variables | プレミティブな数値(`spacing/4` = `16px`など)として定義し、レスポンシブや密度(Compact/Comfortable)のモード切替に直結させるため。 |
| シャドウ・エフェクト(Drop Shadow等) | Styles / Variables(ハイブリッド) | エフェクトプロパティ自体はStylesで保持しつつ、その中の「Color」や「Blurの数値」の部分のみをVariablesで駆動させる。 |

黄金律:カラーと数値はVariables、複合プロパティはStyles

タイポグラフィのように複数のCSSプロパティ(`font-family`, `font-size`, `line-height`, `letter-spacing`)が絡み合うものは、現在のFigmaの仕様上、Text Styleとして定義し、その内部の色やサイズの一部にVariablesを紐付ける、あるいはスタイル自体をコード側のCSS/Tailwindトークンと命名規則で完全に同期させるアプローチを取るのが最も堅牢である。

—

3. 既存デザインファイルのエグゼキューション:移行戦略と自動化

手動で数千のレイヤーのColor StyleをVariablesに置き換える? それはエンジニアの仕事ではない。人間の手作業は必ずヒューマンエラーを生む。
Figma Plugin APIおよびREST API / CLIを駆使し、完全にプログラム制御された移行パイプラインを構築せよ。

以下は、既存のColor Styleをスキャンし、対応するVariables(Primitives → Semantic構造)へとマッピング・置換するためのTypeScriptによるFigmaプラグインのコアロジックである。

自動移行スクリプト(Figma Plugin API)

/

  • Figma Plugin: Styles to Variables Migration Engine
  • 既存のColor Styleを走査し、対応するSemantic Variablesへ安全にバインドし直す

/

interface ColorMapping {
styleName: string;
variableName: string;
}

// 事前に定義されたマッピングテーブル(実際はJSON等からロード)
const migrationMap: ColorMapping[] = [
{ styleName: “color/primary/main”, variableName: “semantic/primary/default” },
{ styleName: “color/surface/background”, variableName: “semantic/bg/canvas” },
];

async function migrateStylesToVariables() {
// 1. ローカルのColor Stylesを取得
const localStyles = figma.getLocalPaintStyles();

// 2. ローカルのVariables(コレクション)を取得
const variableCollections = await figma.variables.getLocalVariableCollectionsAsync();
const targetCollection = variableCollections.find(c => c.name === “Semantic Tokens”);

if (!targetCollection) {
figma.notify(“Error: ‘Semantic Tokens’ collection not found.”, { error: true });
return;
}

const localVariables = await figma.variables.getLocalVariablesAsync();

// 3. ドキュメント内の全ノードを走査し、StyleIdをVariableのバインドへ置換
const nodes = figma.currentPage.findAll(node => ‘fillStyleId’ in node || ‘strokeStyleId’ in node);

let migratedCount = 0;

for (const node of nodes) {
// Fillの移行処理
if (‘fillStyleId’ in node && typeof node.fillStyleId === ‘string’ && node.fillStyleId !== figma.mixed) {
const style = localStyles.find(s => s.id === node.fillStyleId);
if (style) {
const mapping = migrationMap.find(m => m.styleName === style.name);
if (mapping) {
const targetVar = localVariables.find(v => v.name === mapping.variableName && v.variableCollectionId === targetCollection.id);
if (targetVar) {
// 変数をペイントにバインド
const paint = figma.variables.setBoundVariableForPaint(
{ type: ‘SOLID’, color: { r: 0, g: 0, b: 0 } }, // ダミーカラー(変数で上書きされるため何でもよい)
‘color’,
targetVar
);
node.fills = [paint];
migratedCount++;
}
}
}
}
}

figma.notify(`Migration Complete: Successfully migrated ${migratedCount} nodes to Variables.`);
}

// 実行
migrateStylesToVariables();

—

4. CI/CDパイプライン統合:Design TokensからFigma Variablesへの逆流

真のDevOps環境では、Figmaが唯一の真実のソース(Single Source of Truth)であってはならない。GitHubのコードリポジトリ(JSON)こそが真のソースであり、それをFigmaへCI/CD経由で自動同期(Sync)させるべきである。

以下は、W3C形式のデザイントークンJSONをFigma REST API経由でVariablesにインジェストするためのNode.js CLIスクリプトの概念設計だ。

/

  • CLI Script: Sync W3C Design Tokens JSON to Figma Variables
  • GitHub Actions等のCIパイプラインから実行され、Figma上のVariablesを自動更新する

/

import axios from ‘axios’;

const FIGMA_API_TOKEN = process.env.FIGMA_API_TOKEN;
const FIGMA_FILE_KEY = process.env.FIGMA_FILE_KEY;

interface DesignTokenJSON {
[key: string]: {
value: string;
type: string;
};
}

async function syncTokensToFigma(tokens: DesignTokenJSON) {
const endpoint = `https://api.figma.com/v1/files/${FIGMA_FILE_KEY}/variables`;

// Figma Variables REST API Payloadの構築
// ※実際のAPI仕様(POST /v1/files/:key/variables)に基づいたペイロード構成
const payload = {
variableCollections: [
{
action: “CREATE”,
id: “PrimitiveCollection”,
name: “Primitives (Synced via CI)”
}
],
variables: Object.entries(tokens).map(([key, token], index) => ({
action: “CREATE”,
id: `var_${index}`,
name: key,
variableCollectionId: “PrimitiveCollection”,
resolvedType: token.type === ‘color’ ? ‘COLOR’ : ‘FLOAT’,
valuesByMode: {
“default”: token.value
}
}))
};

try {
const response = await axios.post(endpoint, payload, {
headers: {
‘X-Figma-Token’: FIGMA_API_TOKEN,
‘Content-Type’: ‘application/json’
}
});
console.log(“Successfully synced tokens to Figma:”, response.data);
} catch (error) {
console.error(“Failed to sync tokens:”, error.response?.data || error.message);
process.exit(1);
}
}

// 実行サンプル
const sampleTokens: DesignTokenJSON = {
“color/primitive/blue/500”: { value: “#0066FF”, type: “color” },
“spacing/primitive/md”: { value: “16”, type: “dimension” }
};

// syncTokensToFigma(sampleTokens);

—

5. アーキテクトが守るべき運用上の鉄則

1. 名前空間(Namespace)の厳格化:
`primary-color`のような曖昧な命名を禁止する。必ず `primitive/color/blue/500` -> `semantic/action/primary-default` のような階層構造(Slash syntax)を強制し、Figmaとコード(TailwindやCSS Variables)の命名規則を完全一致させよ。
2. スコープ(Scopes)の活用によるポルターガイスト現象の防止:
Variablesの「Scopes」設定を適切に行い、例えばCorner Radius用の変数をColorの塗りに適用できないように制限せよ。デザイナーのヒューマンエラーをUIの制限で物理的に封じ込めるのが、真に優れたデザインシステム設計である。
3. パフォーマンス監視:
Variablesのモード数が過剰に増えると、Figmaファイルのランタイムメモリが肥大化する。マルチブランド対応において、1つのファイルにすべてのブランドのモードを詰め込むのではなく、ブランドごとにファイルを分割し、Publishされたライブラリとして参照(Library swapping)するアーキテクチャを選択せよ。

Stylesの直感性と、Variablesのプログラマビリティ。この二者の境界線を正確に見極め、コードベースと完全に同期したデザイン・インフラストラクチャを構築できたチームだけが、プロダクトのスケールとスピードのジレンマから解放される。

手を動かせ。コードを書け。デザインシステムをエンジニアリングせよ。

タイトルとURLをコピーしました