The Language We Never Agreed On

Ten years of design tokens, several competing formats, and the shared language that never arrived

  • Design Tokens
  • W3C DTCG
  • Style Dictionary
  • Figma Variables
  • Tailwind
  • CSS Variables
  • Tokens Studio

Inside most companies that ship software, the colour of the primary button lives in more than one place. The designers hold it in a Figma file as a variable. The engineers hold it in the codebase as a token, in whatever format the build reads. The marketing site holds its own copy, built in something else again. All three are meant to be the same blue. Someone keeps the three aligned by hand, editing each store when the value changes and checking they still match. The moment that upkeep lapses, they drift apart.

That single source of truth, one value defined once and read everywhere, is what design tokens were invented to provide. For about a decade the design-systems community has been trying to build it. One shared language for visual decisions, a format that designers, developers, AI agents, Figma, iOS, Android and a CMS could all read without translation. There are now at least three serious candidates for what that language should be. Two of the three are actively diverging. The third never tried to take part. Tokens sit on top of the layers they were supposed to remove.

This isn't one team's failure. Every decision along the way was made by people doing good work inside real constraints. The constraints simply don't add up to a shared language. They add up to the appearance of one, which is arguably worse, because it lets everyone assume convergence while the incompatibilities pile up underneath.

A word, then a tool

Nobody called them design tokens before Jina Anne started using the phrase at Salesforce. The story has been told a few times, most recently in Anne's own retelling on the On Theme podcast in 2025. Anne joined Salesforce around 2014 on a small productivity tool. She kept the style values, the colours and type and spacing, in a YAML file, then looped over the data to generate both the style guide and the Sass variables from the one source. When the work moved to the core team that approach was pitched, and it became the foundation for an internal tool called Theo, the first build system made specifically to take design data and emit platform-specific output for the web, iOS, Android and whatever else Salesforce was shipping.

Salesforce had teams on Java, React, Angular and PHP, internally and across the partners building on the platform. A colour change that failed a contrast ratio used to mean notifying the Android team, the iOS team and several web teams one by one. With tokens the change was made once and the downstream platforms pulled the latest.

Anne's formulation, repeated almost ritually since, is that design tokens are a methodology, and that "design tokens are just variables" is like saying responsive design is just media queries. The methodology described a separation rather than a file format. The decision was a sentence: this is the colour for primary actions. That decision resolved to a value, a hex or an RGB triplet or a resource ID. The value was then emitted as platform-specific output, a CSS custom property on the web, a Swift constant on iOS, an XML resource on Android.

/* one decision, emitted for three platforms */
--color-action-primary: #1a56db;                    /* web: CSS */
let colorActionPrimary = UIColor(...)               // iOS: Swift
<color name="color_action_primary">#1a56db</color>  <!-- Android: XML -->

For about three years tokens stayed a Salesforce thing. While other teams knew about the idea, most didn't yet have the tooling to make it practical.

In June 2016 Nathan Curtis at EightShapes published Tokens in Design Systems, which gave the community its first shared way of organising tokens into options (the raw values) and decisions (the semantic aliases that point at them). Those two layers are now usually called primitive and semantic. A year later, in the summer of 2017, Danny Banks open-sourced Style Dictionary from inside Amazon, a build system that could take tokens in JSON and transform them into whatever a platform required, CSS or Swift or Kotlin or Sass. The idea now had both a way of thinking about it and a production tool to run it through.

By 2018 the conceptual frame was complete. Tokens were a methodology, expressed as data, transformed by a build system, organised in layers. The community knew what they were and roughly how to build with them. The one thing missing was agreement on what the data itself should look like. Style Dictionary, Theo and every team's bespoke setup had each invented its own JSON shape, and a token file from one tool couldn't be read by another without translation. That is where the language problem started.

  1. 2014Theo, at SalesforceThe first build system for design data.
  2. June 2016Nathan Curtis's modelOptions and decisions, which most teams now call primitive and semantic.
  3. Summer 2017Style DictionaryTokens in JSON, transformed into whatever a platform needs.
  4. October 2017Tailwind CSS 0.1.0Utility-first, with no decision layer to standardise. It never joins the conversation.
  5. July 2019The DTCG is proposedA W3C community group, to give the industry one format.
  6. 2020Tokens StudioShips its own token types, a year before the first Editor’s Draft is public.
  7. June 2023Figma VariablesModes, which the draft had not settled, shipped under a different word.
  8. November 2024Tailwind v4The config file becomes optional. Theme variables are native CSS custom properties.
  9. October 2025The first stable specificationSix years and three months after the group was proposed.
Ten years of design tokens. Everything between July 2019 and October 2025 shipped while the standard was still in draft, and the native primitive was there for all of it.

Three ways the language split

On 31 July 2019 Kaelig Deloumeau-Prigent, who had worked on design systems at the Financial Times, the BBC, the Guardian, Salesforce and Shopify, proposed a new W3C Community Group. The Design Tokens Community Group set out to provide standards upon which products and design tools can rely for sharing stylistic pieces of a design system at scale.

The First Editor's Draft went to the design-tool vendors, Figma and Sketch and Adobe XD and InVision and Framer and Material Design among a dozen others, on 17 April 2021, and went public that September. A Second Editor's Draft followed in June 2022. The shape had stabilised by then. Tokens were nested JSON objects with $type and $value keys, the dollar sign chosen as a reserved marker so tools could add their own keys alongside without colliding. Composite types like typography, border and shadow became their own token types with structured sub-values. References between tokens used a curly-brace syntax. It was careful work, and by 2022 it was three years old as a community effort and still in draft. While the DTCG iterated, the tools it meant to unify were already shipping their own versions of the same idea without consensus.

// tokens.json, DTCG / W3C format
{
  "colour": {
    "blue-500": { "$type": "color", "$value": "#3b82f6" },
    "action": {
      "primary": { "$type": "color", "$value": "{colour.blue-500}" }
    }
  }
}

Figma went its own way in 2023. At Config that year, its first in-person conference since 2020, Dylan Field announced Variables. As the designer Thalion put it in a Config recap, When Dylan told us they were not launching design tokens on Config, I felt disappointed for a few seconds. Because the newly introduced feature, Variables, will cover all the stuff that tokens should do and even more.

Figma Variables support colours, numbers, text and booleans. They support aliasing. They support modes, several values for the same variable switched as a unit, light and dark, English and Spanish, mobile and desktop. They are reachable by plugin and REST API. In almost every respect they are the thing the DTCG had been working toward for four years, and in a few specific technical respects they are something else.

Mark d'Amato wrote about this within days, in a post called Spicy Specifications. Figma has intelligently chosen the word 'Variable' to opt out of following the specification to support its product features but also offers the import/export of the DTCG specification where appropriate against its Variables. I believe this is the correct direction as the DTCG learns from existing patterns. The diplomatic reading is that Figma needed to ship features the DTCG hadn't finalised, modes especially, and picked a different word to mark the boundary rather than ship a non-standard version of the standard term. The blunter reading, that variables and design tokens are simply not the same thing, is also defensible.

Figma's valuesByMode structure, the mechanism that makes light and dark switching work, stores values keyed by an internal mode identifier. The DTCG's handling of modes was at that point one of its largest open questions, and the community proposals hadn't converged. Figma needed something to ship, so it built valuesByMode.

The result is that the file describing a colour in Figma is not the file describing the same colour in Style Dictionary, even when both go by design tokens. Tokens Studio, which began in 2020 as a Figma plugin and predates both Variables and the DTCG spec, sits in the middle doing the translation, carrying its own conventions from years before either standard existed. A practitioner working across these tools is working in three overlapping but non-identical languages. They share most of their vocabulary but they diverge at theming and semantic structure and composite types and modes.

The Figma Variables panel showing one grey colour ramp under two theme modes, Modern Theme and Brutal Theme, each step holding a different hex value in each mode, with the mode selector set to Default.
Figma Variables in my own design system file, one grey ramp holding a different value under each of two theme modes. Captured August 2026.

In late October 2017, while Style Dictionary was still finding its audience and the DTCG was two years from existing, Adam Wathan released the first version of Tailwind CSS, late on Halloween night. Tailwind's premise, utility-first CSS where interfaces are composed from atomic classes like mx-6 and bg-blue-500 rather than from named semantic components, sidestepped the whole question of what a decision layer should look like. There was no semantic layer in Tailwind because there was no separation between decision and value to maintain. The utility was the value.

To anyone thinking in tokens this was wrong on every count. It conflated decision with implementation, locked aesthetic choices into markup, made theming harder, made platform independence impossible. It made no difference.

Tailwind v1.0 shipped in May 2019. By the time it crossed ten million downloads in August 2020 it was one of the fastest-growing CSS frameworks in the industry, and a generation of developers had learned to style interfaces by reaching for text-slate-700 and space-y-4 rather than by writing or consuming tokens at all.

Tailwind had its own colour scale, Slate and Zinc and Neutral and Stone and the rest, each on a 50 to 950 ramp, its own spacing scale, its own breakpoint names. None of it was tokens in the DTCG sense, but it played the same role, a shared vocabulary of design decisions baked into the tool and used identically across every project that adopted the framework. It just used a different word, config, and a different file, the tailwind.config.js object.

Two posts. Jina Anne arguing that design tokens are a methodology and not just variables, and Adam Wathan announcing the arrival of Tailwind CSS 0.1.0.

Jina Anne, 2018Jina Anne, 2018
Adam Wathan, 2017Adam Wathan, 2017
The two vocabularies, a year apart. Jina Anne in November 2018 and Adam Wathan in November 2017.

A W3C community group standardising a JSON format. A Figma feature called Variables with a proprietary representation. A collection of build tools, Style Dictionary and Tokens Studio and Specify, each translating between formats with their own small variations. And the most widely adopted styling system in the industry treating none of it as relevant.

The same blue, written four ways, in four files that can't read each other.

The tokens community hasn't fully absorbed what happened next. In November 2024 Tailwind released the first public beta of v4, with the full release in early 2025. The headline was a shift to what the team called CSS-first configuration. The tailwind.config.js file, Tailwind's defining piece of infrastructure since 2017, became optional. In its place, an @theme directive written directly in CSS, defining design tokens as CSS custom properties.

@import 'tailwindcss';

@theme {
  --color-primary: hsl(49, 100%, 7%);
  --spacing: 0.25rem;
  --font-sans: ui-sans-serif, system-ui;
}

These low-level design decisions are often called design tokens, the Tailwind v4 documentation reads, and in Tailwind projects you store those values in theme variables. The framework that had spent seven years ignoring the tokens conversation now used the word in its own docs. What Tailwind v4 left alone matters more. It didn't adopt the DTCG format, and it didn't reach for $type and $value. Its theme variables are plain CSS custom properties, declared at the top of a stylesheet, and that stylesheet is the configuration layer. Every utility class resolves to one of those variables, so any other CSS in the document can read the same value.

Tailwind's v4 theme documentation, with the sentence describing low-level design decisions as design tokens stored in theme variables.
Tailwind's own theme documentation, captured August 2026. The framework that spent seven years outside the conversation, using the word.

CSS custom properties have existed in working-draft form since 2012, and gained real browser support around 2017. They predate the DTCG by seven years and Salesforce's token work by two. They are, by any reasonable definition, the native browser primitive for the exact problem tokens were invented to solve on the web. They had been sitting in every major browser, working, for the entire decade the design-systems community spent building a JSON format for the same purpose.

Tailwind v4, in effect, conceded that the native primitive was where web design decisions now lived. The question of where to store them had been answered by the browser in 2017, and the industry had spent eight years acting as though it hadn't.

None of this is the DTCG's failure. The group was always solving a different problem, how to share token definitions across platforms, web and iOS and Android and print, which is the one thing CSS custom properties can't do, because they only exist in the browser. A native iOS app can't read a :root declaration. Nor can a Figma file, except through a translation layer. But the DTCG's framing, JSON as the canonical format with platform-specific output generated downstream, was set when CSS custom properties were still settling into browsers. By the time the spec stabilised the web had moved on. The first stable version of the Design Tokens Specification arrived on 28 October 2025, six years after the community group was proposed. Tailwind v4, which uses the native CSS primitive directly and ignores the spec, had shipped almost a year before that.

The W3C announcement of the first stable Design Tokens Specification, dated 28 October 2025, and the section listing what 2025.10 introduced, including theming, modern colour spaces, token relationships and cross-platform consistency.

The announcementThe announcement
What the release addedWhat the release added
The Design Tokens Community Group's announcement of the first stable specification, 28 October 2025.

Four formats, no floor

There is, today, no single design tokens file format. There are at least four, overlapping heavily and diverging where it counts.

The colour for a primary action, asked of four token formats at once. Each is asked to express a flat value, a reference to another token, and a mode. All four hold the same blue. They diverge on modes: Figma Variables handle them natively, the DTCG spec had not settled them, Tokens Studio bolts them on through separate themes, and Tailwind has no mode construct at all.

One decision, four incompatible files, the same blue in all of them.

The DTCG / W3C format is nested JSON. Each leaf carries a $type (color, dimension, fontFamily, typography, border, shadow) and a $value, references use {group.token} syntax, and composite types like typography are objects with sub-properties for fontFamily, fontSize, fontWeight, lineHeight and letterSpacing. Mode handling, the thing Figma needed for Variables, was still being worked out as of the 2025.10 spec.

Figma Variables are stored proprietarily inside Figma files. The internal representation is valuesByMode, each variable holding a map of mode IDs to values, exportable through the REST API or the official DTCG transformer plugin, which converts Variables into DTCG-shaped JSON and loses some fidelity on the way, because the two formats treat modes and references differently.

Tokens Studio began as the Figma Tokens plugin in 2020, before the DTCG spec was public, and its native format carries token types that pre-date the spec, borderWidth and borderRadius and composition, which the spec later folded into broader types or dropped. It now supports both its legacy format and the W3C one, with utilities to convert between them. A team adopting it in 2026 picks one of the two at setup and lives with the choice.

Tailwind theme variables are native CSS custom properties in an @theme block, scoped to whatever selector the developer uses. They aren't stored as JSON, aren't portable off the web, aren't transformable through Style Dictionary. They are pure CSS, which is the same reason they run on the web with no tooling overhead and have nothing to interpret them on iOS.

A team building across platforms in 2026 has to choose from these formats, and the choices compound. If the designers work in Figma Variables, the engineers in Style Dictionary and the marketing site in Tailwind, primary blue exists in three representations inside one company. Each is canonical where it lives, and overruling any one breaks the workflow built on it. This is the fragmentation tokens were meant to remove, rebuilt one level up. The three hold the same value in different forms, the build tools keep them roughly in step, and the inconsistencies that slip through fall between the three owners rather than to any one of them.

The temptation is to read this as a coordination failure. If only Figma had adopted the spec, or Tailwind had taken part, or the W3C had moved faster, or Tokens Studio had aligned sooner. Coordination problems are solvable when the parties want to coordinate. Each of these had good reason not to.

Figma's priorities in 2022 didn't line up with the DTCG's. Figma needed to ship Variables with mode support, the DTCG hadn't settled mode handling, and shipping anyway under a different word was the rational move. Tailwind's priorities never lined up with the cross-platform framing the DTCG was built around. Tailwind exists for the web and is right not to pay coordination costs for problems it doesn't have. The DTCG, run by volunteers drawn from competing vendors, could only move as fast as consensus allowed. Everyone acted reasonably, and nobody had any incentive to give ground for the sake of a shared language.

Ten years on, the field has more vocabulary for tokens than it has agreement on what they are.

That is the shape of every attempt to build a lingua franca in a competitive market. Nobody chooses defection, everyone chooses their own constraints, and the aggregate is incompatibility. Character encodings before Unicode. The metric system in the United States. Bluetooth audio codecs. The plug sockets that still differ from one country to the next. When a standard competes against tools that ship faster than it can finalise, the tools win, and the standard ends up one format among several rather than the base layer everyone builds on.

What it's for now

It would be easy to take all of this as a verdict on the DTCG project. The 2025.10 specification is, on its own terms, excellent work. The $-prefixed keys let tools extend the format without breaking compliance. The composite types, typography and border and shadow, are carefully thought through. The reference syntax is unambiguous. After years of collaborative development, the specification provides a production-ready, vendor-neutral format for sharing design decisions across tools and platforms, the announcement says, and that is true. It is also the smaller half of the claim that mattered when the project began.

The larger claim, that the DTCG would become the shared language across the industry, hasn't happened, and the evidence suggests it won't. What the spec is good for in practice is narrower and real. It gives a team a defensible, vendor-neutral format for the cross-platform layer of a token system. For a product shipping on iOS, Android and the web from a single source of truth, the DTCG format plus Style Dictionary is the cleanest answer going, and the one most resistant to vendor lock-in, since a tokens file written to DTCG stays portable across Tokens Studio, Style Dictionary and, with translation, Figma. That is a genuine position in the stack. It is one tool among several with a particular set of strengths, not the floor everyone stands on.

It is also why a fair number of teams now write their cross-platform tokens in DTCG-compliant JSON, transform them through Style Dictionary, and emit CSS custom properties for the web alongside platform-specific output for everything else. With no format having become the standard, DTCG is the one most likely to stay readable in five years, across the most tools, with the least translation overhead. That is why teams reach for it. Writing tokens in DTCG keeps a file portable while the formats around it diverge.

This matters more now than it did three years ago, because the consumer of a tokens file has changed. For most of that history, the audience was human engineers reading documentation, or build systems running deterministic transforms. Both cope with fragmentation. An engineer reads the docs, learns the format and translates as needed. A build system follows the rules it was given. AI coding agents do neither. When Cursor or Claude Code reads a design system to generate a component, the format the tokens are written in is the interface. The agent has to parse whatever the system actually contains, DTCG JSON or a Figma Variables export or Tokens Studio format or raw CSS custom properties, and each needs a different parse strategy and yields a slightly different picture of what the design decisions are.

A system written in DTCG-compliant JSON, with explicit $type and $value keys and structured references, is far easier for a model to reason about than a Tailwind config. Not for any failing in Tailwind, which models read fine, but because the DTCG format carries more semantic information per token. The file alone tells the agent that this is a colour, that this is a dimension, that this one references another token rather than copying its value, and the agent can write code that respects those distinctions. This is the strongest practical argument for the DTCG spec, and the one the original 2019 proposal could never have made, because the audience it speaks to didn't yet exist.

In 2026 the layer tokens created is increasingly read by machines, and machines need a format precise about its own structure. DTCG happens to be that format. It was designed by people thinking carefully about structure while most of the field was still thinking about CSS.

The consequential choice is what the semantic layer contains, which intent aliases exist, what they mean, how they relate to the primitives underneath. That layer can be written in DTCG JSON or Tailwind config or Figma Variables, and the container matters less than what goes in it. A primitive token records a fact. blue-500 is #3B82F6. A semantic token records a judgement. surface-interactive is blue-500, because someone decided what an interactive surface is in this product. The fact can be automated. The judgement has to be made by a person who has thought about what the product is, and in most teams it doesn't get made. That absence shows up downstream as inconsistent components, engineers caught off guard, and tokens whose reason has been lost.

// a primitive records a fact
"blue-500": { "$value": "#3b82f6" }

// a semantic token records a judgement
"surface-interactive": { "$value": "{colour.blue-500}" }

A beautifully DTCG-compliant file whose semantic layer is a thin wrapper over the palette, surface-1, surface-2, surface-3, with nothing said about what makes each surface different, is a translation layer over a non-decision. The format is correct and the thing it encodes is empty. Turn it around. A homegrown JSON shape no other tool can read, but a semantic layer someone has actually worked out, every alias with a reason and every reference with a real intent behind it. That is the stronger system of the two. A standard cannot supply the thinking it was built to carry. Only the thinking can.

Tokens were supposed to be the shared language between design and engineering. They became another layer of translation instead. There is no right format yet, and there may never be one. A token resolves to the same colour whether it lives in DTCG JSON, a Figma variable or a Tailwind theme. The format was never the hard part. Whether anyone decided what the colour means is the part no file can carry and no tool can translate.