The breaking point
I was reviewing a pull request last Tuesday. A developer on my team was trying to implement a new theme switcher for our dashboard. They had imported a massive JSON file of design tokens from our repository. Then they wrote a giant JavaScript context provider to swap out the values dynamically on the client side.
I left a comment asking why they didn't just use native CSS variables. They replied that our design system pipeline only exported SCSS variables and raw JSON. That moment really cemented a thought I've been having for a long time. If you build products for the web, CSS variables are the only design token format you should care about.
Let's look at how most teams handle design tokens right now. A designer updates a colour in Figma. An automated script pulls that data via an API. The script runs it through a massive transformation pipeline. Then it spits out a dozen different files. You get SCSS variables. You get Less variables. You get a JavaScript object. You get a TypeScript interface. It feels like you are covering all your bases and being incredibly thorough.
But this creates a massive headache for the developers actually building the product. When you give people too many options, they often pick the wrong one for the job.
The problem with compiled tokens
Take SCSS variables as an example. They are entirely static. They compile at build time and then they are gone forever. If you want to support a dark mode using SCSS variables, you have to write twice as much CSS. You end up overriding classes or generating multiple massive stylesheets.
$color-bg-light: #ffffff;
$color-bg-dark: #121212;
.card {
background-color: $color-bg-light;
}
body.dark-mode .card {
background-color: $color-bg-dark;
}
This approach is exhausting. It bloats your compiled CSS completely unnecessarily. It makes maintaining UI components a total nightmare. Every single time you add a new element, you have to remember to write the specific dark mode override for it.
Now look at native CSS custom properties. They are incredibly dynamic. They live natively in the browser. They actually understand the cascade. You define your tokens exactly once at the root level. Then you redefine them for your dark theme. Your actual component CSS never has to change at all.
:root {
--color-bg: #ffffff;
}
[data-theme="dark"] {
--color-bg: #121212;
}
.card {
background-color: var(--color-bg);
}
The component just asks for the background colour. The browser figures out which value to use based on the context. This is fundamentally better. It is cleaner. It requires significantly less code.
The debugging nightmare
There is another massive benefit that people completely ignore. I am talking about debugging.
Imagine you are trying to figure out why a button looks wrong on staging. You open Chrome DevTools. If your team uses a JavaScript theme provider or compiled SCSS, inspecting the button just shows a raw hex code. You see #007bff applied to the background. You have absolutely no idea which design token that maps to. You have to go search your codebase for that specific string.
If you use CSS variables, DevTools tells you the exact story. You inspect the button and see var(--button-primary-bg). You know exactly what token is driving the design. You can even click it in DevTools to see where the value is defined and test out changes right there in the browser.
What about utility frameworks?
I hear this specific complaint all the time. People tell me they use Tailwind CSS, so they don't need CSS variables. They just map their JSON tokens straight into their configuration file.
Honestly, that is a missed opportunity. You should absolutely plug your design tokens into your utility framework. But you should configure your Tailwind theme to consume your CSS variables, not raw hex codes. This lets you keep all the benefits of utility classes while letting the browser handle theme switching automatically via the cascade. You don't need to write dark:bg-gray-900 on every single div. You just write bg-surface and let the CSS variable change its own value based on the theme data attribute.
The native app argument
Now I know what some of you are thinking. You are going to say that your company also builds native iOS and Android applications. You need your design tokens in Swift and XML formats.
That is a completely fair point. If you actually deploy native mobile apps, you absolutely need those native formats. But tbh, most teams aren't doing that. Most teams are building web applications. They build dashboards and marketing sites. Yet they still copy the complex architectural patterns used by massive tech giants. You don't need a multi platform token pipeline if you only ship to the web.
Keeping it simple
So what do you actually do about this. You simplify your architecture. You cut out the middleman entirely.
You should export your Figma variables straight to CSS. You skip the massive JSON parsing scripts. You skip the complex build steps. You just get the CSS variables directly into your codebase.
This is exactly why I built the Design System Sync plugin. I wanted a way to skip all that painful boilerplate. The plugin takes your Figma design tokens and exports them directly to GitHub or Bitbucket via automatic pull requests. You can export standard W3C Design Tokens if you need them. But more importantly, you can export perfectly formatted CSS variables right out of the box. It handles multiple modes like light and dark themes automatically.
You can check out the plugin on Figma Community right here: https://www.figma.com/community/plugin/1561389071519901700?utm_source=devto&utm_medium=post&utm_campaign=bot
Or you can read more about how the GitHub integration works on the website: https://ds-sync.netlify.app?utm_source=devto&utm_medium=post&utm_campaign=bot
We really need to stop fighting the browser. Stop writing complicated JavaScript to do a job that CSS handles natively. Stick to custom properties. Your components will be smaller. Your debugging process will be faster. Your developers will be much happier.
Are you still forcing your team to use compiled SCSS variables for design tokens?
Top comments (0)