Integration · Setup

Figma variables Into CSS custom properties, and back

Figma hands over its variables in two ways: design token files from its own export, or JSON from its REST API on Enterprise plans. A small script, figma-to-css.mjs, turns either into CSS custom properties, one block per mode. The sample files reproduce every step, and both the request and the answer were checked against Figma’s published API types.

Needs
Node.js 18 or later
Cost
Free script; your Figma plan sets the route
Checked

Before you start

What you need

  • Node.js 18 or later. The script has no dependencies.
  • For Figma’s export: a file with variables, open in Figma’s editor.
  • For the REST API: an Enterprise plan, a full seat, and a personal access token with the file_variables:read scope.

What Figma can do

Four ways in and out of Figma

As Figma’s help center and REST API documentation describe them. None was run against a real Figma file from here; the last column says what was checked instead.

Ways to move variables in and out of Figma
RouteWhat it doesWho can use itChecked here
Export modes, in the variables panelWrites design token files in the DTCG format, one per mode. Numbers carry no unit.Anyone editing the file; Figma’s help names no plan for it.The script reads files in that format; the samples were written here, not exported.
Import modes, in the variables panelCreates or updates variables from DTCG files: colors in sRGB or HSL, dimensions in px (they become plain numbers), a single font family, durations in seconds, and numbers. An alias to another collection links only through com.figma.aliasData.As for export.Not used here.
REST API: read variablesGET /v1/files/:file_key/variables/local returns every local variable and collection, with every mode.Full members of Enterprise organizations, with file_variables:read.The sample answer type-checks against @figma/rest-api-spec 0.44.0.
REST API: write variablesPOST /v1/files/:file_key/variables creates and changes collections, modes and variables.Full members of Enterprise organizations, with file_variables:write.The token studio’s request type-checks against @figma/rest-api-spec 0.44.0.

From Figma’s export

From Figma’s export to CSS

  1. Export the modes

    In Figma’s variables panel, right-click a collection and choose Export modes, or right-click one mode and choose Export mode. Save the files in one folder.

  2. Get the script

    Download figma-to-css.mjs into the same folder. It is one file, with its rules written at the top.

    Download the script

  3. Turn them into CSS

    List the files of the default mode first. Put --mode and a name before each other mode’s files; they go under [data-theme] with that name. Figma’s export keeps no unit, so list the groups whose numbers are pixels after --px.

    Terminal

    node figma-to-css.mjs Primitives.Value.tokens.json Theme.Light.tokens.json \
      --mode dark Theme.Dark.tokens.json --px space,radius,font-size,breakpoint --out tokens.css

    You should see: a :root block and a [data-theme="dark"] block, each variable named after its Figma name: color/primary is --color-primary.

From the REST API

From the REST API to CSS

  1. Read the variables

    Ask Figma for the file’s local variables with your token, and save the answer. The file key is the part of the file’s address after /design/.

    Terminal

    curl "https://api.figma.com/v1/files/$FILE_KEY/variables/local" \
      -H "X-Figma-Token: $FIGMA_TOKEN" \
      -o variables.json
  2. Turn them into CSS

    Give the script the saved answer on its own. Each collection’s default mode goes in :root; its other modes go under [data-theme], named after the mode.

    Terminal

    node figma-to-css.mjs variables.json --out tokens.css

    tokens.css, the dark mode’s first lines

    /* Theme · Dark */
    [data-theme="dark"] {
      --color-canvas: var(--color-neutral-1000);
      --color-surface: var(--color-neutral-950);
      --color-surface-raised: var(--color-neutral-900);
      --color-text: var(--color-neutral-0);
      --color-text-muted: var(--color-neutral-300);
      --color-border: var(--color-neutral-500);
      /* … */
    }

    You should see: blocks like this one, every variable of the collection again in each mode, so components follow a nested theme.

Reproduce it

Files to reproduce it

The token studio’s default system, as Figma would hold it. Run the script on the REST answer and compare: the two CSS files should match byte for byte.

The files, and what each one is
FileWhat it is
figma-to-css.mjsThe script.
variables.example.jsonA REST API answer for the token studio’s default system: the studio’s Figma request applied as Figma’s documentation describes, then read back. It type-checks against Figma’s types; it was not taken from a real file.
Primitives.Value.tokens.json
Theme.Light.tokens.json
Theme.Dark.tokens.json
The same variables as one DTCG 2025.10 file per mode, ready for Figma’s Import modes. Each theme value that points at a primitive names the Primitives collection in com.figma.aliasData, so Figma links it. Figma’s own exports carry extra fields, which the script ignores.
tokens.expected.cssWhat the script writes from variables.example.json.

Terminal: run it, then compare

node figma-to-css.mjs variables.example.json --out tokens.css

# macOS and Linux
diff tokens.css tokens.expected.css

# Windows, in Command Prompt or PowerShell
fc.exe tokens.css tokens.expected.css

To try it in Figma: in a new file, create a variable collection named exactly Primitives and drag Primitives.Value.tokens.json into it. Create one named Theme and drag in both theme files, which become its Light and Dark modes. Export both collections with Export modes, and run the command under “From Figma’s export” on the files Figma writes.

How it converts

Names, modes and values

  • Names. A variable’s Web code syntax when it has one; otherwise its name, groups joined by hyphens, in lower case. Color/Brand 500 becomes --color-brand-500. Two variables that would share a name stop the script with both names.

  • Colors become hex, with an alpha pair below full opacity. A color with its own opacity becomes color-mix().

  • Numbers get px when every scope they have is a size, radius, gap, stroke, effect, font size or paragraph setting, or, from Figma’s export, when their name is in a group listed after --px; otherwise they stay plain numbers. Figma holds numbers to about seven digits, so values are rounded to four decimals: 10.239999771118164 is 10.24.

  • Aliases become var(), so a role still points at its primitive in the CSS.

The other way

From CSS tokens back to Figma

The token studio writes a request for Figma’s POST endpoint that creates the same collections, with each variable’s CSS name set as its Web code syntax, so Figma’s Dev Mode shows the name your code uses.

Send the tokens to Figma

Limits

What it does not do

  • Nothing here has been run against a real Figma file. The REST answer is modelled on Figma’s documentation and type-checked against its published types; the DTCG files follow the DTCG 2025.10 format.
  • Figma’s import turns px dimensions into plain numbers, and its export writes them back without a unit, as a real file showed on 19 October 2026. The command puts px back on the groups named after --px; a group you add needs adding there too.

  • Figma users report that its export leaves out variable descriptions and composite tokens such as typography and shadows.
  • The script skips extended collections and DTCG composite tokens, and names each one in a warning.
  • Booleans come out as the words true and false, which CSS properties cannot use directly; keep them for your own scripts.

Privacy and access

Where your work stays

  • The script runs on your machine and sends nothing anywhere.
  • Your Figma token is used only in the command you run yourself.

Go further

The full reference

Checked against

Where these facts come from

Versions, requirements and examples on this page were checked on . The sample answer was made from the token studio’s Figma request; both were type-checked with TypeScript 7.0.2 against @figma/rest-api-spec 0.44.0, and the script’s CSS was compared with the studio’s own for every role in both themes. Figma’s capabilities are from its help center and REST API documentation. Neither route has yet been run on a real Figma file: the answer and the token files follow Figma’s documentation.

Found a mistake? Write to us and we will correct it.