A Tailwind CSS theme from design tokens in one command
I design interfaces and build them myself. I have a style library, pbstyles: its colors, sizes and fonts are described as design tokens. I wanted the Tailwind theme to be built from those tokens instead of rewriting it by hand after every change in Figma. That's how tailwind-dictionary came about. I

t takes tokens in JSON and builds a Tailwind CSS theme from them. Light and dark themes are built from the same files. It's useful if you already have tokens but don't want to switch to Tailwind because you'd have to maintain the theme separately. Or if you're already on Tailwind and want to export variables from Figma and get a theme right away.
AI can pull variables from Figma and build a theme. But AI tokens cost money, and the theme gets rebuilt after every design change. Spending them on the same routine task is a waste; better save them for harder problems. Also, AI may build the theme slightly differently each time.
With the package, you set up the build once. After that it's one command, and the same tokens always give the same theme. It reads tokens in the new W3C Design Tokens format (DTCG 2025.10) and in the legacy Style Dictionary format. Exports from Figma, Tokens Studio and Terrazzo work.
It builds a theme for Tailwind 4 and Tailwind 3. You can have as many themes as you need: light, dark, high contrast, a second brand. The theme includes colors, sizes, fonts, text styles, shadows, breakpoints and animations. All configuration lives in one config.json.
Your editor suggests its fields and highlights mistakes. There's a --watch mode that rebuilds the theme when tokens change. Figma exports variables on its own: in the Variables panel, right-click a collection β Export modes. You get one *.tokens.json file per mode.
Let's take a simple example. The palette and radii live in a collection without modes. The primary, background and foreground colors live in a collection with Light and Dark modes and reference the palette. Here's the palette: { "color": { "blue": { "600": { "$type": "color", "$value": { "colorSpace": "srgb", "components": [0.149, 0.388, 0.922], "alpha": 1, "hex": "#2563EB" }, "$extensions": { "com.figma.variableId": "VariableID:1:3" } } } }, "radius": { "4": { "$type": "number", "$value": 4 } } } And here's the Light mode: { "color": { "primary": { "$type": "color", "$value": "{color.blue.600}" } } } You can't paste this into CSS as is.
The color is an object, primary references another variable, and the radius has no unit: a browser won't understand --radius-4: 4. The package sorts all of this out. npm install --save-dev tailwind-dictionary Put the palette in tokens/Primitives.tokens.json and the modes in tokens/Light.tokens.json and tokens/Dark.tokens.json. Next to them, create config.json: { "version": 4, "source": ["tokens/Primitives.tokens.json"], "themes": { "light": ["tokens/Light.tokens.json"], "dark": ["tokens/Dark.tokens.json"] }, "output": "./styles", "themeAliases": { "color": "color", "radius": "radius", "spacing": "1px" } } source holds the tokens shared by all themes, themes holds the theme files.
In themeAliases, the left side is the Tailwind theme key and the right side is the token group. If your radii are called rounded in Figma, write "radius": "rounded". The "spacing": "1px" line sets the spacing step: p-16 gives exactly 16 pixels, just like in the design. Run the build and import the result after Tailwind: npx tailwind-dictionary @import 'tailwindcss'; @import './styles/tailwind/theme.css'; Now bg-primary, text-foreground and rounded-4 work in your project.
The theme.css file, with the light theme removed for brevity: :root { --theme-color-primary: #2563eb; --theme-color-background: #f9fafb; --theme-color-foreground: #111827; } [data-theme='dark'] { --theme-color-primary: #3380f5; --theme-color-background: #111827; --theme-color-foreground: #f9fafb; } @theme { --*: initial; --color-*: initial; --color-blue-400: #3380f5; --color-blue-600: #2563eb; --color-gray-50: #f9fafb; --color-gray-900: #111827; --radius-0: 0; --radius-4: 4px; --radius-8: 8px; --spacing: 1px; } @theme inline { --color-primary: var(--theme-color-primary); --color-background: var(--theme-color-background); --color-foreground: var(--theme-color-foreground); } Colors became plain hex values, references were replaced with values. The radius 4 became 4px. You can change the unit with the numberUnit option: "rem" divides the number by 16, false leaves it as is. The --*: initial line removes Tailwind's default theme.
Only your values stay in the project, and a stray bg-blue-500 that isn't in the design simply won't build. Theme colors live in --theme-color-*, and Tailwind references them through @theme inline. Thanks to inline, bg-primary compiles to background-color: var(--theme-color-primary), and the value is resolved on the element that has the class. So you can switch the theme anywhere on the page: <html data-theme="dark"> <body> <section data-theme="light">A light block on a dark page</section> </body> </html> Without the attribute, light and dark follow the system setting.
The attribute on <html> overrides it, which is what a theme switcher on a website needs. Figma doesn't export variable descriptions. Text styles and shadows aren't in the export either: in Figma they're styles, not variables. I describe them as tokens by hand, and a typography token h64 becomes a text-h64 class with size, line height and weight at once.
Don't put theme files in source. If you write tokens/**/*.json and your themes are in tokens/themes/, the same tokens come in twice. The package also reads the legacy Style Dictionary format, but you can't mix it with the new one in a single build. When something's wrong, the error is a single line with the token and file name: β Token "color.text" (tokens/color.json) references {color.nope}, which is not defined In the playground you can paste your own Figma export and immediately see the theme and a preview in light and dark.
Everything runs in the browser; your tokens are not sent anywhere. The package doesn't sync with Figma on its own: you export manually and commit the files. It doesn't build components either, only the theme. If your project doesn't use Tailwind, the sibling package mixin-dictionary builds CSS variables and LESS/SCSS mixins from the same tokens.
Package page Β· GitHub Β· npm Β· Docs How to export variables from Figma pbstyles tokens β an example with two themes This article was written with the help of AI, based on my notes, and reviewed by me. The code examples were checked against tailwind-dictionary 2.6.2.
Key Takeaways
- β’Light and dark themes are built from the same files.
- β’This story was reported by Dev.to, covering developments in the dev space.
- β’AI advancements continue to reshape industries β read the full article on Dev.to for complete coverage.
π Continue reading the full article:
Read Full Article on Dev.to βShare this article


