By following this guide, you will set up a fully working Figma variable mode system that handles light mode, dark mode, and multi-brand theming from a single token structure. The entire workflow takes around two to three hours to build from scratch, and once it is done, your design and development teams share one source of truth for every colour, spacing, and typography decision.

What You'll Build

  • A Figma variable collection with at least three modes: Light, Dark, and Brand A
  • Semantic alias tokens that reference primitive tokens, so you swap themes by switching a mode rather than repainting every frame
  • A working proof-of-concept component (a card) that responds correctly when you toggle between all three modes
  • A variable export structure that maps cleanly to CSS custom properties and Tailwind theme config
  • A repeatable naming convention your team can follow for every new token you add

Prerequisites

  • Figma Professional or Organisation plan (variable modes require a paid seat as of mid-2025)
  • Figma desktop app version 116 or later
  • Basic familiarity with Figma components and Auto Layout
  • Optional: the Tokens Studio plugin if you plan to sync tokens to code

Step 1: Understand the Two-Layer Token Model

Before touching Figma, get clear on the structure you are building. Every production-grade token system uses two layers.

The first layer is primitives. These are raw values with no semantic meaning: color/blue/500, color/neutral/100, size/4. They never change between modes.

The second layer is semantics. These are aliases that point to primitives: color/background/surface points to color/neutral/100 in Light mode and to color/neutral/900 in Dark mode.

When a designer switches the mode on a frame, only the semantic layer changes. The primitives stay put. This is what makes multi-theme design scalable instead of painful.

Why does this matter for teams in 2026?

Figma's native variables now export directly to JSON via the Variables REST API (released in full in late 2024). If your token structure mirrors the two-layer model, your developer can consume that JSON without a conversion step. That saves roughly 30 to 60 minutes per release cycle.

Step 2: Create Your Primitive Collection

Open Figma. Go to the Local Variables panel (right-hand panel, click the grid icon). Click Create collection and name it Primitives.

Add colour variables using this naming pattern:


color/blue/100
color/blue/200
color/blue/300
color/blue/400
color/blue/500
color/blue/600
color/blue/700
color/blue/800
color/blue/900

color/neutral/0
color/neutral/100
color/neutral/200
...
color/neutral/900
color/neutral/950

color/red/500
color/green/500
color/yellow/500

Forward slashes create groups in Figma's variable panel. Keep every group flat at two levels deep: category then scale step. Deeper nesting creates confusion without adding clarity.

Add a single mode called Default. Primitives never need multiple modes. Set raw hex values for every variable now.

What if I already have a colour palette from a brand guide?

Import your brand's hex values directly. You are not inventing colours at this stage, you are cataloguing them. If the brand guide only gives you five blues, add five steps. You can always expand the scale later.

Step 3: Create Your Semantic Collection With Modes

Create a second collection. Name it Semantics.

Click the + button next to Modes and add three modes: Light, Dark, and Brand A. Set Light as the default.

Now add your semantic variables. Use role-based names, not colour names:


color/background/page
color/background/surface
color/background/overlay

color/text/primary
color/text/secondary
color/text/disabled
color/text/on-accent

color/border/default
color/border/strong
color/border/focus

color/accent/default
color/accent/hover
color/accent/active

color/feedback/error
color/feedback/success
color/feedback/warning

For each variable, click the value cell under the Light column. Instead of entering a hex value, click the library icon and select the matching primitive variable. For example, color/background/page in Light mode maps to color/neutral/0.

Repeat for every semantic variable across all three modes. In Dark mode, color/background/page maps to color/neutral/950. In Brand A, it might map to a completely different neutral family.

Common pitfall: what if I set a raw hex instead of an alias?

If you type a hex value directly into a semantic variable, you break the alias chain. That variable will not update when you switch modes. Always use the variable picker, not the colour picker, when setting values in the Semantics collection.

Step 4: Add Spacing and Typography Tokens

Colour gets the most attention, but spacing and typography variables are equally important for consistent theming.

Create a third collection called Scale. Add a single Default mode. Add number variables for spacing:


spacing/1   → 4
spacing/2   → 8
spacing/3   → 12
spacing/4   → 16
spacing/5   → 20
spacing/6   → 24
spacing/8   → 32
spacing/10  → 40
spacing/12  → 48
spacing/16  → 64

Figma does not yet support font-family or font-weight as variables natively (as of September 2026), but you can store font-size as a number variable and apply it via the text style binding in Pro. Store your type scale values here so they are available for your developer's token export even if Figma itself does not bind them yet.

Step 5: Apply Variables to a Test Component

Build a simple card component to prove the system works before rolling it out across your file.

Create a frame with:

  • A background rectangle
  • A heading text layer
  • A body text layer
  • A button with a filled background
  • A border (use a stroke on the frame)

Select the background rectangle. In the Fill panel, click the hex value chip. Switch from the colour picker to the variable picker using the icon in the top-right corner of the popup. Select color/background/surface.

Apply variable bindings to every element:

  • Heading text: color/text/primary
  • Body text: color/text/secondary
  • Button fill: color/accent/default
  • Button text: color/text/on-accent
  • Frame stroke: color/border/default
  • Frame padding: spacing/4 on all sides via the padding variable input

Select the parent frame of your card. In the right panel, find the Variable mode option (the small grid icon near the layer name). Switch between Light, Dark, and Brand A. Every colour should update instantly. If any element stays the same colour across modes, that element has a raw value instead of a variable binding.

What if the mode switcher does not appear on my frame?

The mode switcher only appears on frames, not on groups or components directly. Wrap your component in a frame, or use the component's parent frame. Also confirm your Figma seat is on a paid plan, as mode switching is not available on the free tier.

Step 6: Export Variables for Development

Once your variables are working in Figma, connect them to code. There are two practical paths in 2026.

Path A: Figma Variables REST API

Use a personal access token and call the API directly:


curl -H "X-Figma-Token: YOUR_TOKEN" \
  "https://api.figma.com/v1/files/YOUR_FILE_KEY/variables/local"

The response includes every variable and every mode value. Parse it with a small Node.js script to output CSS custom properties:


// parse-tokens.mjs
import fs from 'fs';
const data = JSON.parse(fs.readFileSync('./variables.json', 'utf-8'));

const modes = data.meta.variableCollections;
const vars = data.meta.variables;

const cssLines = [];
for (const [id, v] of Object.entries(vars)) {
  if (v.resolvedType !== 'COLOR') continue;
  const lightValue = v.valuesByMode[/* light mode id */];
  if (lightValue?.type === 'VARIABLE_ALIAS') continue; // skip aliases in primitives
  cssLines.push(`  --${v.name.replace(/\//g, '-')}: ${toHex(lightValue)};`);
}

fs.writeFileSync('./tokens.css', `:root {\n${cssLines.join('\n')}\n}`);

This script is a starting point. A production parser handles aliases, floating-point RGBA values, and mode branching. Expect to spend about an hour making it production-ready.

Path B: Tokens Studio Plugin

Install the Tokens Studio for Figma plugin. Connect it to your GitHub repo. It reads your Figma variables, converts them to the W3C Design Tokens format (formerly DTCG), and pushes a JSON file on every sync. Your CI pipeline then runs Style Dictionary to generate CSS, Tailwind config, or iOS Swift files from that JSON.

Teams at Lenka Studio typically recommend Tokens Studio for projects where design and development are running in parallel sprints, because the GitHub sync creates an automatic audit trail of every token change.

Step 7: Document the Naming Convention for Your Team

A variable system fails when team members add new tokens without following the structure. Write a one-page guide and pin it to your Figma file cover page.

The guide should answer four questions:

  • Where do primitives live and who can add them?
  • Where do semantics live and what naming pattern must new tokens follow?
  • How do you add a new mode, and who approves it?
  • What is the export workflow when a token changes?

If your team uses a design system documentation site, copy the naming rules there too. A brand health check is a good moment to review whether your token governance is keeping up with your product's growth. You can use the free brand health score assessment to identify gaps across brand, design, and digital consistency before they compound.

Frequently Asked Questions

How many modes can a Figma variable collection have?

As of September 2026, Figma allows up to 40 modes per collection on the Organisation plan, and 4 modes on the Professional plan. For most products, three to five modes (light, dark, two or three brand variants) cover every real use case.

Can I use Figma variables with Tailwind CSS?

Yes. Export your token JSON via the Variables REST API or Tokens Studio, then run Style Dictionary to output a Tailwind theme extension file. Map your semantic tokens to Tailwind's color, spacing, and fontSize keys. Your developers reference bg-background-surface instead of a hex value, and the theme updates globally when you push a token change.

What is the difference between Figma variables and Figma styles?

Figma styles store a fixed value (one colour, one text style, one shadow). Variables store a value that can change per mode. Variables replaced styles for colour theming in most professional workflows after 2024, because you can switch an entire frame's theme with one click instead of reapplying styles manually.

Does this workflow work for iOS and Android tokens too?

Yes. Style Dictionary, which processes your exported JSON, ships with built-in formatters for iOS Swift, Android XML, and Kotlin. You write the token once in Figma and generate platform-specific output files in CI. Teams using React Native typically target the CSS custom property and JavaScript ES module outputs rather than the native platform formats.

What if my team is on Figma's free plan?

The free plan supports creating variables but limits you to one mode per collection. You can still build the two-layer primitive and semantic structure, but you cannot switch modes inside Figma. You can still export the variable JSON via the API and manage mode logic in code. It is a reasonable starting point for a solo founder or small team before upgrading.

Next Steps

Start with Step 2 today, even if you only add ten primitives. A partial variable system is more useful than none. Once your card component is proving the mode switch works correctly, roll the variable bindings out to your most-used components first: buttons, inputs, and navigation.

From there, connect the export pipeline in Step 6 so your developers are consuming the same token values the design file produces. That connection is where the real time saving happens across a product team.

If you want a second opinion on your token architecture before scaling it across a large design system, the team at Lenka Studio works with product companies across Australia, Singapore, Canada, and the US on exactly this kind of foundation work. Get in touch and we can review your current structure and suggest a path forward.