Known limitations
What to know before building Scalar’s output. These are lasting limits, not bugs: either something the DTCG 2025.10 format can’t express, or a deliberate choice to keep the output strictly valid.
Scalar never drops anything silently. Each item below is either kept in the token’s $extensions
or listed in the export report, usually both. “Lost” here means $value alone isn’t enough to
rebuild the original intent; the information is still in the file.
Figma features Scalar can’t export yet
Section titled “Figma features Scalar can’t export yet”- Extended Collections (Figma Enterprise) aren’t exported. They’re left out and named in the report.
- References to library variables (variables from another Figma file) can’t be resolved yet: they’re written as placeholders and counted in the report. Terrazzo stops on them; Style Dictionary reports them as broken references.
Git sync on self-hosted servers is untested
Section titled “Git sync on self-hosted servers is untested”Sync is tested on github.com and gitlab.com. It’s built to work with self-hosted GitLab and GitHub Enterprise too (set the host in Settings), but hasn’t been tried on a real one yet. If it fails, Download ZIP still works.
Colors with a separate opacity are flattened
Section titled “Colors with a separate opacity are flattened”A color variable that points to another color but sets its own opacity is exported as a plain
color with that opacity applied. The link to the base color is not in $value; the base color and
opacity are kept in $extensions under com.figma.composedColor.
- Why: DTCG has no “this token, at a different opacity” construct. A value is either a reference or a color, never both. Figma’s own export flattens these too.
- What it means: if the base color changes, this token doesn’t follow it until you export again.
Blur and other non-shadow effects are skipped
Section titled “Blur and other non-shadow effects are skipped”Background blur, layer blur, noise, texture and glass effects aren’t exported, and the report
names each one. Only drop and inner shadows have a DTCG type (shadow).
Typography extras live in $extensions
Section titled “Typography extras live in $extensions”Italic, text case (uppercase etc.) and text decoration (underline, strikethrough) aren’t part of the
typography $value. They’re kept in $extensions as com.figma.fontStyle, com.figma.textCase
and com.figma.textDecoration.
- Why: a DTCG typography value has exactly five fields (font family, size, weight, letter spacing, line height), and nothing else is allowed.
- What it means: a standard build ignores them. To use them, read
$extensionsin a custom transform. The CSSfontshorthand can’t carry them anyway: they need separate properties (text-transform,text-decoration,font-style).
Other Figma-only text settings (paragraph spacing and indent, list spacing, hanging punctuation,
leading trim, text wrap, underline style, offset, thickness and color) follow the same rule. They’re
kept in $extensions only when they differ from Figma’s defaults.
OpenType features aren’t exported
Section titled “OpenType features aren’t exported”Ligatures, alternate characters and other OpenType features on a text style aren’t exported: Figma doesn’t give plugins access to them. Set them in your platform code if you need them.
Bound line height becomes a fixed multiplier
Section titled “Bound line height becomes a fixed multiplier”A text style whose line height is bound to a variable exports its line height as a number (px ÷
font size, e.g. 28 ÷ 20 = 1.4), not as a reference. The binding is kept in
$extensions["ext.scalar"].boundLineHeight, and the variable itself exports as a px dimension.
- Why: Figma applies a bound line height as px, but a DTCG typography line height is a multiple of the font size. A reference to the 28px variable would mean 28× the font size.
- What it means: the built style doesn’t follow the variable; change it and export again. The multiplier comes from the default mode, so if the line height or font size changes between modes, it’s wrong in the other modes. The report flags those styles. An unbound % line height avoids all of this.
Font weights bound through a text variable become numbers
Section titled “Font weights bound through a text variable become numbers”When a text style’s weight is set through a text variable (a value like "Bold"), the
typography fontWeight is the resolved number (700). The binding is kept in
$extensions["ext.scalar"].boundFontStyle. A weight bound to a number variable stays a live
reference.
Font-weight variables on their own stay text
Section titled “Font-weight variables on their own stay text”A standalone font-weight variable is a text variable in Figma, so it exports as $type: string
with its value as written ("Bold", "SemiBold"). Scalar doesn’t guess that "Bold" means 700.
Typography tokens that use it still get the number; only the standalone token keeps the name. Map
names to numbers in your build if you use these tokens directly.
A token with tokens nested under it becomes $root
Section titled “A token with tokens nested under it becomes $root”A variable or style named like a group of others (text/warning next to text/warning/strong)
is exported as that group’s $root token, and references to it read {text.warning.$root}.
- Why: a DTCG entry can’t be both a token and a group.
$rootis the format’s own answer. - What it means: the value is unchanged; only the path gains
$root. Terrazzo names it after the group (--text-warning), and so does Style Dictionary 5.7.1. Older Style Dictionary versions get the name and references wrong; see Building with Style Dictionary. - The official DTCG JSON schema also rejects
{….$root}references, even though the format spec requires them (design-tokens/community-group#448). A validator using that schema will flag them.