Choosing Figma Variables or Styles for Your Design System Tokens
Decide whether to use Figma Variables or Styles for your design tokens. Compare token types, theming, and developer handoff in a clear table, then walk through a concrete export example and validation checklist.
19 Sept 2025, 03:57 UTC

Decision Context
When building a design system in Figma, the core question is whether to store design tokens as Variables or Styles. Both are library‑level primitives, but they differ in supported data types, theming capabilities, developer handoff, and migration paths. This guide distills the constraints and offers a clear decision matrix, followed by a concrete export example and validation checklist.
What Are You Trying to Achieve?
- Support multiple themes (light, dark, high‑contrast) in a single file.
- Expose semantic tokens (e.g.,
color.primary) that can be aliased and referenced across components. - Provide developers with a clean, resolved JSON or CSS file that includes mode context.
- Maintain a workflow that allows designers to publish tokens without breaking downstream consumers.
- Keep performance acceptable for large libraries.
Comparison Table
| Feature | Variables | Styles |
|---|---|---|
| Supported Token Types | Color, Number, String, Boolean | Color, Text, Effect, Grid (no Number/String/Boolean) |
| Theming (Modes) | Built‑in, per‑collection, multi‑mode support | Not supported; requires separate collections or files |
| Aliasing / References | Full aliasing, math expressions, chain depth limit 10 | No aliasing; each style is independent |
| Developer Export | REST API /variables/local returns mode context and resolved aliases | REST API /styles lacks mode data; requires post‑processing |
| Component Binding | Can bind Number/String/Boolean to instance swap, text, boolean props | Only Color, Text, Effect, Grid can be bound |
| Migration Path | One‑way conversion from Style to Variable for colors; no reverse | No direct support for Variable types |
| Performance | UI lag above ~5,000 Variables; alias resolution may slow | Generally lighter; Styles panel remains responsive |
| Permissions | Requires edit access on the library file | Can be published from view‑only team libraries |
| Plugin Ecosystem | Newer API (figma.variables), evolving tool support | Well‑established APIs (figma.paintStyles, etc.) |
Trade‑Off Analysis
- Token Coverage: If your system needs semantic tokens, spacing, or boolean flags, Variables are mandatory. Styles cannot hold these types.
- Theming: Variables natively support modes, eliminating the need for duplicate files or manual theme switching.
- Developer Handoff: Variables expose mode context in the API, simplifying automated build pipelines. Styles require extra parsing logic.
- Performance: For lightweight color palettes, Styles may be preferable. For large token sets (>5k), consider a hybrid approach: keep primitive Variables and critical Styles separate.
- Governance: If your organization restricts edit rights for library files, Styles can be published from view‑only libraries, whereas Variables cannot.
Hybrid Strategy Recommendation
Most production systems benefit from a hybrid model:
- Use Variables for semantic tokens (color, spacing, typography, boolean flags).
- Keep Styles for quick effect presets (shadows, blurs) and gradient/Image assets that Variables cannot store.
- Maintain a single
ThemeVariable collection that includes all mode values; mirror critical style values in a lightweight Style collection for consumers that cannot import Variables.
Concrete Implementation: Exporting Variables with Mode Context
Below is a step‑by‑step example of how to pull a Variable collection from a Figma file, resolve modes, and output a JSON token file for developers.
- Prerequisites:
- Figma personal access token with
files:readscope. - File key of the library containing Variables.
- Node.js environment (or any HTTP client).
- Figma personal access token with
- API Call:
curl -H "Authorization: Bearer PERSONAL_ACCESS_TOKEN" \ https://api.figma.com/v1/files/FILE_KEY/variables/localExpected response contains
variableCollections, each withmodesandvariables. Variables may reference others viaaliasobjects. - Resolve Modes and Aliases:
const resolveVariable = (varObj, collection) => { if (varObj.alias) { const parentVar = collection.variables.find(v => v.id === varObj.alias.id); return resolveVariable(parentVar, collection); } return varObj.values[activeMode]; };Loop over each collection, apply the active mode (e.g.,
light), and flatten the result into a key/value map. - Output JSON:
{ "color": { "primary": "#0066FF", "secondary": "#FF6600" }, "spacing": { "s": "4px", "m": "8px" }, "boolean": { "isEnabled": true } }Developers can import this file directly into their CSS/SCSS variables or TypeScript enums.
Validation Checklist
- Open the library file in Figma; ensure Variables panel lists all expected tokens.
- Publish the library and verify the Variables appear in the Assets panel of a consumer file.
- Run the API script; compare the JSON output against a hand‑crafted snapshot of token values.
- In Dev Mode, toggle a mode (e.g., switch from light to dark) and confirm component colors update to the correct Variable values.
- Measure the Variables panel load time with a file containing >5,000 Variables; if UI lags, consider splitting into smaller collections or using Styles for non‑semantic tokens.
Limitations & Caveats
- Variables cannot store gradients or images; use Styles for those assets.
- Alias chains longer than 10 levels may not resolve; keep your token architecture flat.
- Cross‑file Variable references require the library to be published; unpublished Variables are not consumable.
- Boolean Variables cannot directly control layer visibility; use component boolean props instead.
- REST API exports do not include resolved mode values for remote consumers; integrate a build step that resolves modes per target platform.
Conclusion
If your design system demands rich theming, semantic tokens, and developer‑friendly exports, Variables are the primary mechanism. Use Styles only for assets that Variables cannot hold or for lightweight color/text libraries. A hybrid approach gives you the best of both worlds while keeping performance and governance manageable.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.