An opinionated translation utility that transforms Figma-exported CSS variables into clean, organized, production-ready CSS custom properties.
- Removes comments and consolidates duplicate variables - Cleans up Figma's verbose export format
- Simplifies variable names - Removes redundant prefixes (e.g.,
--border-border-xs→--border-xs) - Smart unit conversion - Converts px values to rem (with smart exceptions)
- Responsive typography - Creates fluid font-size variables using CSS
clamp() - Theme support - Separates light and dark mode variables with media queries
- Dynamic color detection - Automatically detects and groups color palettes
- Layer wrapping - Wraps output in
@layer globalsfor better CSS cascade control - Organized output - Groups and sorts variables logically by type and purpose
The easiest way to use this tool is with npx, which runs the package without installing it globally:
# Basic usage (reads original.css, outputs output.css)
npx @netzstrategen/figma-variables
# Custom input and output
npx @netzstrategen/figma-variables ./src/figma-export.css ./src/globals.css
# Only specify input (outputs to output.css)
npx @netzstrategen/figma-variables ./src/figma-export.cssIf you use it frequently in a project:
npm install --save-dev @netzstrategen/figma-variablesFor system-wide usage:
npm install -g @netzstrategen/figma-variables
figma-variables ./src/figma-export.css ./src/globals.css# Basic usage
npx @netzstrategen/figma-variables
# Transform specific files
npx @netzstrategen/figma-variables ./src/figma-tokens.css ./dist/tokens.css
# Get help
npx @netzstrategen/figma-variables --help
# Check version
npx @netzstrategen/figma-variables --versionAdd to your package.json:
{
"scripts": {
"tokens": "npx @netzstrategen/figma-variables ./src/figma-tokens.css ./src/design-tokens.css"
}
}Then run:
npm run tokensimport { transformCSS } from '@netzstrategen/figma-variables';
transformCSS('./input.css', './output.css');This tool expects CSS exported from Figma with the following structure:
:root {
/* PRIMITIVES */
--color-primary-50: #eaf0fc;
--color-primary-100: #d9e5fa;
--color-primary-500: #253fe4;
--border-border-xs: 1px;
--border-border-xs-rem: 0.0625rem;
/* STYLEGUIDE */
--surface-surface-background-light-mode: var(--color-default-50);
--surface-surface-background-dark-mode: var(--color-default-950);
}The tool generates clean, organized CSS:
@layer globals {
:root {
--color-primary-50: #eaf0fc;
--color-primary-100: #d9e5fa;
--color-primary-500: #253fe4;
--border-xs: 0.0625rem;
--font-size-step-0: clamp(1.125rem, 1.0786rem + 0.1905vw, 1.25rem);
--surface-background: var(--color-default-50);
}
@media (prefers-color-scheme: dark) {
:root {
--surface-background: var(--color-default-950);
}
}
}--border-border-xs→--border-xs--size-size-24→--size-24--surface-surface-background→--surface-background--typography-font-body→--font-family-body
- Converts to rem: Most spacing, sizing, and border values
- Keeps px:
spacing-px,radii-full, and specific edge cases - Removes redundant units:
0px→0,0rem→0
Variables ending in -light-mode and -dark-mode are:
- Separated into base
:root(light mode) and@media (prefers-color-scheme: dark)blocks - Stripped of their mode suffix
- Organized by category (surface, text, icon, outline)
Font size variables are transformed into fluid typography using clamp():
/* Input */
--font-size-min-step-0: 18px;
--font-size-max-step-0: 20px;
/* Output */
--font-size-step-0: clamp(1.125rem, 1.0786rem + 0.1905vw, 1.25rem);Variables are automatically organized into groups:
- Colors (primary, secondary, tertiary, etc.)
- Layout (container, header)
- Typography (font-family)
- Borders & Radii
- Spacing & Sizing
- Semantic tokens (surface, text, icon, outline)
The tool automatically detects color groups. Known colors appear in a preferred order, while new colors are added alphabetically:
Known order:
color-defaultcolor-graycolor-primarycolor-secondarycolor-tertiarycolor-highlightcolor-accent
New colors (e.g., color-brand, color-custom) are automatically detected and placed alphabetically.
Run tests with Vitest:
npm testRun tests in watch mode during development:
npm run test:watchTests verify:
- Correct transformation of CSS variables
- Variable name simplification
- Unit conversion accuracy
- Mode separation (light/dark)
- Output structure and formatting
- Error handling
This project uses GitHub Actions for automated testing. Tests run automatically on:
- All push events (any branch)
- All pull requests
Tests are executed on multiple Node.js versions (20.x, 22.x) to ensure compatibility.
You can test GitHub Actions workflows locally using act before pushing to the repository:
# Install act (macOS)
brew install act
# Run workflows locally
act push
# Run specific job
act -j test
# See detailed guide
cat .github/ACT.mdThis allows you to test changes to workflows without polluting your git history with test commits.
# Clone the repository
git clone <repository-url>
# Install dependencies
npm install
# Run tests
npm test
# Run tests in watch mode
npm run test:watch
# Transform example files (local development)
node index.js original.css output.css
# Or test with npx locally
npx . original.css output.css- Node.js 20.x or higher (ES Modules support)
- No external dependencies for production (uses only Node.js built-in modules)
- Vitest for testing (dev dependency only)
MIT
Issues and pull requests are welcome! Please ensure:
- Tests pass (
npm test) - Code follows existing style conventions
- Commit messages are clear and descriptive
Before publishing, ensure:
- All tests pass:
npm test - Version is updated in
package.json - CHANGELOG.md is updated
- You're logged in to npm:
npm login
To publish:
npm publish --access public- Support for custom transformation rules
- Configuration file support
- Plugin system for custom processors
- CSS-in-JS output format option
- TypeScript type definitions generation