Design System Problems

Token Resolution Order

January 15, 2026 • 5 min read

Token Resolution Order

Token resolution order determines how final token values are computed when multiple definitions, overrides, or inheritance levels exist. In complex token systems with themes, brands, and component overrides, the same token name might have different potential values. Resolution order rules establish which value applies in any given context.

What Is Token Resolution Order

Token resolution order is the sequence of precedence rules that determines which token definition wins when multiple sources define the same token. This includes precedence between base tokens and theme overrides, between global tokens and component-scoped tokens, and between different inheritance layers.

Predictable resolution order enables developers to understand what value a token will have without tracing through complex conditional logic.

How Token Resolution Order Works

Resolution typically follows a layered approach where more specific definitions override more general ones.

Basic layer precedence (low to high):

  1. Base/default tokens
  2. Theme tokens
  3. Brand tokens
  4. Component tokens
  5. Instance overrides

A token defined at each layer would resolve to the instance override value.

Example with CSS custom properties:

/* Layer 1: Base */
:root {
  --color-primary: blue;
}

/* Layer 2: Theme override */
[data-theme="dark"] {
  --color-primary: lightblue;
}

/* Layer 3: Brand override */
[data-brand="secondary"] {
  --color-primary: green;
}

/* Layer 4: Component scope */
.button {
  --color-primary: purple;
}

An element within .button in dark theme with secondary brand would see:

Build-time resolution for generated tokens:

// Resolution order configuration
const layers = [
  'tokens/base/**/*.json',
  'tokens/themes/dark/**/*.json',
  'tokens/brands/secondary/**/*.json'
];

// Later files override earlier files for matching token names
const resolved = layers.reduce((acc, pattern) => {
  const tokens = loadTokens(pattern);
  return { ...acc, ...tokens };
}, {});

Key Considerations

Common Questions

How does CSS specificity affect token resolution?

CSS specificity rules determine which property declaration applies when multiple rules target the same element. Token values delivered via CSS custom properties follow these same rules.

Specificity hierarchy:

  1. Inline styles (highest)
  2. ID selectors
  3. Class, attribute, and pseudo-class selectors
  4. Element and pseudo-element selectors
  5. Universal selector and inherited values (lowest)

Tokens and specificity:

/* Specificity: 0-1-0 (one class) */
.button {
  --button-color: blue;
}

/* Specificity: 0-2-0 (two classes) */
.button.primary {
  --button-color: green;
}

/* Specificity: 0-1-1 (one attribute + one element) */
[data-theme="dark"] button {
  --button-color: lightblue;
}

Understanding CSS specificity helps predict which token value applies in complex styling scenarios.

Avoiding specificity wars:

How should resolution be debugged?

Debugging resolution involves determining why a particular value applies.

Browser DevTools inspection: CSS custom properties appear in element inspection. The Computed tab shows the resolved value. The Rules tab shows which declarations apply.

Resolution tracing: Build tools can log resolution decisions:

function resolveWithTrace(tokenName, layers) {
  const trace = [];
  let value;

  layers.forEach(layer => {
    if (layer.tokens[tokenName]) {
      trace.push({ layer: layer.name, value: layer.tokens[tokenName] });
      value = layer.tokens[tokenName];
    }
  });

  console.log(`Resolution trace for ${tokenName}:`, trace);
  return value;
}

Documentation of overrides: Maintaining records of intentional overrides helps distinguish expected behavior from bugs.

What about resolution in JavaScript-based systems?

React, Vue, and other JS-based applications may implement token resolution through context or state.

React context resolution:

const TokenContext = createContext(baseTokens);

function TokenProvider({ theme, brand, children }) {
  const tokens = useMemo(() => ({
    ...baseTokens,
    ...themeTokens[theme],
    ...brandTokens[brand]
  }), [theme, brand]);

  return (
    <TokenContext.Provider value={tokens}>
      {children}
    </TokenContext.Provider>
  );
}

Nested context override:

<TokenProvider theme="light">
  {/* Uses light tokens */}
  <TokenProvider theme="dark">
    {/* Inner context overrides with dark tokens */}
  </TokenProvider>
</TokenProvider>

JS-based resolution offers explicit control but requires careful context management. The merging strategy (shallow vs. deep) affects how nested token objects combine.

Summary

Token resolution order determines final values when multiple definitions exist for the same token. Layer-based precedence from general to specific provides predictable resolution. CSS specificity rules affect web-based token resolution. Debugging requires understanding both token layers and platform-specific resolution behavior. JavaScript-based systems implement resolution through context merging with explicit control over combination strategies.

Buoy scans your codebase for design system inconsistencies before they ship

Detect Design Drift Free
← Back to Token Management