Design Token Naming Conventions
A design token name is a path, read from broad to narrow:
category-concept-variant-state — as in color-background-subtle,
space-4, text-heading-lg. The conventions that hold up over time follow
five rules: name the decision rather than the value, put position before
appearance for primitives, put role before context for semantics, reserve a
fixed set of state suffixes, and pick one case convention exactly once.
Everything below those rules — bg or background, sm or small — is a
micro-decision to make once, write down, and stop revisiting.
This article covers the naming conventions that cut across every token category; it is the naming chapter of our design tokens guide. Color and typography add domain-specific arguments on top of these rules — the rules themselves are the shared floor.
How is a token name structured?
As a path where each segment narrows the previous one. The category
says what kind of value this is (color, space, text); the concept
says what part of the interface it serves (background, border,
heading); the variant distinguishes siblings (subtle, raised,
lg, 4); the state — when present — names an interaction condition
(hover, disabled). Not every name uses all four segments: space-4 is
a category and a variant with nothing in between, because spacing has no
concepts to distinguish.
Two convention families carry the same path. Hyphen-case writes it flat —
color-background-subtle — which is what CSS custom properties want. Dot
paths write it as nesting — color.background.subtle — which is what
the DTCG format produces, where groups are nested objects and the name is the
path to the leaf. The mapping between the two is one mechanical line:
replace dots with hyphens and prefix --, and every DTCG path becomes a
valid custom property name. Because the mapping is mechanical, the design
work — choosing the segments — transfers unchanged between formats; only
the punctuation is format-specific.
Which naming rules survive contact with reality?
1. Name the decision, not the value. This is the law at the heart of
what design tokens are, and
every token category instantiates it: brand-600 survives the rebrand that turns the
brand teal, while blue-600 either lies about its contents or forces a
rename across every file that references it. The same law rules out
space-16px (false the day the step retunes to 14) and favors names that
state what a token is for — because the “for” is the stable fact and the
value is the volatile one.
2. Position before appearance, for primitives. 600 names a place in
a ramp; dark describes how the value happens to look today. When a ramp
is retuned — the lightness curve adjusted, a step inserted — positions keep
their meaning while appearance words quietly stop being true: is
blue-dark still darker than blue-darker after the retune? Numbered
positions survive every retune by never claiming anything about the value.
3. Role before context, for semantics. text-primary names a job and
transfers to every screen that has primary text; article-heading-color
names a place and is stranded there. Contexts multiply without bound —
article, card, modal, sidebar, settings — while roles stay countable: most
systems need a dozen or two. Naming by role keeps the token set the size of
the role list instead of the size of the product.
4. Reserve the state suffixes. Declare a short, fixed vocabulary —
-hover, -pressed, -focus, -disabled, -selected — that only ever
appears at the end of a name and only ever means interaction state. The
payoff is prediction: anyone who knows fill-brand exists can write
fill-brand-hover without opening a file. An unreserved vocabulary decays
into fill-brand-hover, fill-brandHover2 and fill-brand-mouseover
living side by side.
5. Pick one case convention and never revisit it. kebab-case, camelCase or dot paths — the evidence for any one being superior is thin, which is exactly why the debate never ends on merits. Naming conventions are one of programming’s oldest debate magnets, and token naming inherits the tax: teams can burn weeks here, and the weeks buy nothing, because any consistent convention outperforms a perfect one still being debated — consistency is what rules 1–4 and every export in the toolchain depend on. Decide in one meeting, write the decision down, close the topic.
Open a generated token system and read its names across formats — the same paths written as DTCG groups, as CSS custom properties and as Figma variable names, the segments visible in each rendering.

Should it be bg or background, sm or small?
It matters less which you pick than that you pick once and write it down. These micro-decisions are where naming debates hide after the big rules are settled, so here is a defensible set of picks, one line of reasoning each:
| Micro-decision | Common pick | Why it holds |
|---|---|---|
background vs bg | Spell it out | Search and autocomplete find whole words; the abbreviation saves keystrokes the editor already saves |
small/medium/large vs sm/md/lg | Abbreviate the size ladder | The ladder is memorized as a unit, not read word by word |
| Singular vs plural categories | Singular: color, not colors | Each name reads as one decision, not a bin of them |
| Zero-padded numbers | Unpadded: space-4, not space-04 | Padding only rescues naive alphabetical sorting |
| Ramp step numbers | Hundreds, 50–900 | Leaves room to insert a step without renaming its neighbors |
The table’s job is to be finished, not perfect. If your team already spells half of these the other way, keep the existing picks and document them — an inherited consistent convention outranks a better inconsistent one, which is rule 5 again wearing different clothes.
What makes a token name good?
It can be predicted by someone who has never seen it. That is the working
test: show a new team member color-background-subtle and
color-text-primary, then ask what a subdued border would be called. If
they answer color-border-subtle — and it exists — the convention is doing
its work.
The intuitive reason predictability matters more than elegance: a naming convention is a small grammar, and people generalize from grammars automatically after a handful of examples. Names that follow the grammar are predicted rather than looked up — every correct prediction is a documentation search that never happens, an almost-duplicate that never gets minted, a review comment that never needs writing. Names that break the grammar each cost a lookup, forever. The test also runs in reverse: if every name needs the docs open, the names carry no structure worth learning.
What does one component’s token set look like, named well and badly?
A card component needs five color decisions. Here they are twice — once as token sets tend to accrete when nobody holds a convention, once following the rules above:
| Decision | Ad hoc | Convention |
|---|---|---|
| Card fill | cardBg | color-surface-raised |
| Card border | card_outline_gray | color-border-subtle |
| Title text | CardTitleColor | color-text-primary |
| Card fill on hover | cardBgHover2 | color-surface-raised-hover |
| Button fill | blueDark | color-fill-brand |
Both columns render the same card today. The left column’s problems are all
future problems: three case conventions in five names (rule 5); blueDark
names a value and will lie after a rebrand (rule 1); card_outline_gray
breaks two rules in one name — a context and an appearance — so the next
component that needs the same border either borrows a “card” token or
mints a duplicate (rules 2 and 3); cardBgHover2 carries an unreserved
state and a mystery serial number (rule 4). The right column resolves
through a semantic layer into ramp
steps derived from one seed — on this
palette #2563eb, which is oklch(0.546 0.215 262.9) — and its sixth
token is guessable before it exists: a pressed state on the button would be
color-fill-brand-pressed, and every reader already knows it.
Stress-test the names against change
A naming scheme proves itself at events, not in review meetings: rebrands, ramp retunes, dark mode. Load a token file and rename one value-named primitive to a decision name — re-export, and the round-trip preserves every section you didn’t touch; then change the seed and watch the renamed token keep telling the truth while the value underneath it moves.