How do you move Figma Variables into CSS without losing fidelity?
You define tokens once in Figma Variables (or styles + variables), map them to a stable naming scheme, export them into CSS custom properties — and, for WordPress, wire the same values into theme.json — then make components consume tokens instead of raw hex codes or pixel values. The workflow that survives refactors has three rules: one canonical name per concept, primitive vs semantic layers so theming stays possible, and a handoff artifact both design and code read from. Done well, a color rename in Figma becomes a one-line change; done poorly, it becomes forty scattered hex edits across templates.
This is the unglamorous foundation under every consistent build. Spacing that always snaps to scale, type that matches the design at every breakpoint, dark mode that does not require a second design file — all of it comes from token discipline, not from eyeballing. Start from the structural requirements in our Figma handoff checklist and the delivery model in our white-label Figma-to-WordPress process.
Token types every web project needs
| Type | Examples | Figma Variables collection | CSS output shape |
|---|---|---|---|
| Color | Brand blue, surface, text, border, success, danger | color (+ mode for light/dark) | --color-brand-500, --color-text |
| Space | 4, 8, 12, 16, 24, 32, 48, 64… | space (number/float) | --space-4 → often 0.25rem-based scale |
| Typography | Font families, sizes, line-heights, weights, tracking | Variables + text styles | --text-h1-size, --font-sans, --leading-tight |
| Motion | Durations, easings, distances | motion (number in ms / custom ease strings) | --duration-200, --ease-out-quart |
| Radius / elevation / layout | Corner scale, shadows, z-index tiers, container widths | Separate collections as needed | --radius-md, --shadow-1, --z-header |
Motion tokens matter more than agencies expect: they keep GSAP durations and CSS transitions speaking the same language. When design says “accelerate all reveals to 180ms,” it should be one token change — see motion web development for how those tokens feed production timelines.
Figma Variables → CSS custom properties workflow
1. Separate primitives from semantics
Primitives are raw scales: blue/500, gray/100, space/16. Semantics answer intent: color/background/default, color/text/muted, space/section/gap. Components bind to semantics only. When rebranding, you remap color/brand/primary → blue/600 and every button updates. If buttons hardcode #0A66FF, you are editing CSS forever.
2. Name consistently
Pick one convention and document it:
--color-brand-primary
--color-surface-raised
--space-4
--text-display-lg
--duration-fast
--ease-standard
- Prefix everything (
--color-,--space-) to avoid collisions with third-party CSS. - Use lowercase kebab-case; no camelCase in CSS layers.
- Reference scale steps by token number, not by rem value in the name (
--space-4, not--space-1rem) — rem values change if root font-size does. - Group with nested maps in docs even if CSS is flat.
3. Choose an export path
- Manual / Tokens Studio (Figma plugin): sync a JSON token file (W3C design-token format is a good target), transform to CSS with Style Dictionary or a small build script. Best control, CI-friendly.
- Tokens Studio → GitHub → build: design pushes tokens, pipeline publishes
tokens.css. Strong for agencies with review workflows. - Hand-export critical values: acceptable for small sites, dangerous at scale — drift starts the first time someone edits Figma without updating CSS.
Whatever path you choose, CSS should be generated or verified against the source file in CI (even a simple diff of expected variable names) so silent drift fails the build.
4. Emit CSS custom properties
:root {
--color-brand-primary: #0a66ff;
--color-text: #12161c;
--color-surface: #ffffff;
--space-4: 1rem;
--text-display-lg: clamp(2.5rem, 1.2rem + 4vw, 4rem);
--duration-200: 200ms;
--ease-standard: cubic-bezier(0.2, 0.8, 0.2, 1);
}
[data-theme="dark"] {
--color-text: #e8eaed;
--color-surface: #12161c;
}
Use raw hex in token definitions only. Everywhere else, reference var(--…). For fluid type, tokens can hold clamp() — the semantic token stays stable while the math lives in one place.
theme.json: the WordPress-native layer
WordPress block themes and hybrid themes can consume the same token ideas through theme.json: color.palette, spacing.spacingSizes, typography.fontSizes, and layout settings. Values declared there surface in the block editor, so content authors pick brand colors without hex drift. A common pattern:
- Generate
tokens.css(custom properties for the frontend and for GSAP/motion code). - Map palette + spacing + font size scales into
theme.json(same values, WordPress-friendly slugs). - Keep
theme.jsonas the source for editor UI; keep CSS custom properties as the source for components and motion. - CI checks that slugs in
theme.jsonmatch token names — or generatetheme.jsonfragments from the same JSON token source.
This dual output is the heart of a maintainable Figma-to-WordPress pipeline: design updates one variable collection, both artifacts regenerate.
Theming and dark mode without a second design file
- Define semantic tokens with modes (Figma Variables modes: Light / Dark; CSS:
[data-theme]or media query forprefers-color-scheme). - Never fork components for dark mode — fork token values only.
- Test contrast in both modes (WCAG AA for text); token-level contrast checking beats auditing pages one by one.
- Remember third-party embeds and images with baked-in backgrounds; you may need overlay tokens or component exceptions.
Anti-patterns to reject in review
- Raw hex/spacings in components. Instant review failure.
- Naming tokens after implementation details (
--blue-042) instead of intent — unreadable in six months. - One giant “misc” collection in Figma — nobody trusts it, so people create rogue variables.
- Token per page — if you need
--hero-title-sizeand--about-title-size, you need a type scale, not two tokens. - Updating Figma but not CSS (or the reverse) with no pipeline — the definition of drift.
- Skipping motion tokens so GSAP hardcodes
0.4everywhere. - Editor palette diverging from frontend — authors pick a “brand” color that does not exist on the live site.
Handoff checklist (design → dev → client)
- Variables organized into named collections with documented purpose
- Primitives vs semantics clearly split; components bind to semantics
- Naming convention written down (prefixes, case, scale steps)
- Export pipeline produces CSS custom properties (and JSON for tooling)
theme.jsonpalette/spacing/fontSizes aligned with tokens- Dark/light modes defined for semantic color tokens
- Motion duration/easing tokens included and referenced by CSS + GSAP
- Unused or orphaned variables deleted
- CI or checklist step fails on drift between Figma export and repo CSS
- Devs know which file to edit when a value changes (answer: Figma + regenerate — not “search the CSS”)
Run this checklist inside the same gate you already use for layout QA — visual fidelity and token fidelity fail the same way: quietly, then everywhere at once. The broader delivery sequence lives in our white-label process guide.
FAQ: design tokens from Figma to CSS
What is the difference between Figma styles and Figma Variables?
Styles cover paints, text, effects, and grids in a single mode. Variables add typed values (color, number, string, boolean), aliases, scopes, and modes — which is what makes light/dark theming and multi-brand systems practical. Use Variables for tokens; keep styles where they express composite presentation (e.g., a text style referencing variable sizes).
Do we need Style Dictionary or can we hand-write CSS variables?
Hand-writing works for a small site with one developer. Add Style Dictionary (or any token transform in CI) when multiple people edit tokens, when you need multiple outputs (CSS, theme.json, Swift/Android if applicable), or when you want name/alias validation. The cost is a small pipeline; the payoff is no silent drift.
How do tokens interact with responsive typography?
Keep the semantic name stable and put responsiveness in the value: --text-h1: clamp(2rem, 1rem + 3vw, 3.5rem). Alternatively, define breakpoint-specific overrides in one place (@media on :root). Avoid per-breakpoint token names unless the hierarchy genuinely changes, not just the size.
Should animations use design tokens too?
Yes. Duration and easing tokens keep CSS transitions, Web Animations, and GSAP aligned with design intent. Expose them on :root and read them from JS via getComputedStyle or pass them at init. It also makes reduced-motion policy easier to enforce centrally.
How does this fit white-label agency work?
Tokens are the contract between the agency’s design file and the build the client receives. Documenting the pipeline means any future team — yours, ours, or the client’s — can extend the system without reverse-engineering hex values from screenshots. That is how Figma-to-WordPress projects stay editable years later.
Read next: white-label web development for agencies · pixel-perfect Figma to WordPress development · GSAP motion and page transitions
