Skip to content

Authoring for a clean export

Scalar exports what your Figma file actually says. When something is left unspecified, it makes the safest guess that is still valid and tells you in the report, instead of failing or hiding it.

So the report is your to-do list. Every line in it has a fix in Figma, and an empty report means your system is fully specified. Scalar never edits your values on the way out: Figma is the source of truth, so fixes belong there.

Scope every variable. Scalar decides a token’s type from the variable’s scope in Figma (Width/Height, Gap, Corner radius, Font size, Opacity, …), never from its name or value.

  • A scoped number becomes the right type, with no warning. A number scoped to a size becomes a dimension in px.
  • An unscoped number becomes a plain number and is reported. Guessing it’s a size could break a build, so Scalar doesn’t.
  • One exception: an unscoped number that a size variable points to is exported as a size too, because how it’s used is evidence of what it is.

Scope opacity variables as Opacity. This one fails silently if missed. An opacity scale authored as 0–100 (40 for 40%) exports as the plain number 40 unless it has the Opacity scope. A name like “Opacity/40%” isn’t enough. Downstream, opacity: 40 simply clamps to fully opaque, with no error. With the Opacity scope, Scalar converts it to 0.4, keeps the original 40 in the token’s metadata, and reports the change.

Bind to variables where you can. A size, spacing, radius or weight bound to a variable exports as a reference to that token ({size.md}) instead of a copied number, so the exported system stays connected the way it is in Figma.

Set all five properties. A DTCG typography token needs font family, size, weight, letter spacing and line height. Anything left to Figma’s default forces a guess.

Line height: use %. A percentage maps exactly to the format’s multiplier (150% → 1.5), with no warning.

  • Auto depends on the font’s internal metrics, which plugins can’t read. It exports as 1.2 and is reported.
  • px is converted to a multiplier (px ÷ font size). That’s only right at that one font size, so keep px for a deliberate baseline grid.
  • A bound line-height variable is always px in Figma (there’s no % option when binding). It’s converted to a multiplier the same way, so the style stops following the variable once built. If the variable or font size changes between modes, the multiplier is only exact in the default mode, and the report says so. If line height should scale with the text, use an unbound %.

Font weight: use standard style names (Regular, Medium, SemiBold, Bold, …). They map to 400, 500, 600, 700. An unusual style name can’t be mapped; it falls back to 400 and is reported.

Binding a weight? Use a number variable with the Font weight scope. It exports as a live reference. A weight bound through a text variable (a value like "Bold") can only be exported as its resolved number, with the binding kept in metadata.

Letter spacing in % is converted to px using the style’s font size; px passes through. Both are fine, but % depends on font size.

Names are made safe for the output: spaces become hyphens, and the characters { } . ; are removed. Casing and structure are left as you wrote them. When a name changes, the original is kept in the token’s metadata and listed in the report.

Two names that end up the same after this clean-up (Brand Blue and Brand-Blue) can’t both be exported. The export stops and lists every clash, so you can rename them in Figma.

A variable named like a group of others (text/warning next to text/warning/strong) is fine. It exports as the group’s own token (see Known limitations).

The report lists, in plain language, only what you might need to check or fix. A short or empty report means a healthy file. A long one points at something under-specified in Figma, and each warning goes away for good once it’s fixed there.