Global vs Local Tokens
Global vs Local Tokens
Understanding global vs local tokens helps design system architects make appropriate scoping decisions. Global tokens provide system-wide values accessible everywhere, while local tokens exist within bounded contexts. The balance between global and local scoping affects flexibility, encapsulation, and the ability to make targeted changes.
What Are Global and Local Tokens
Global tokens are tokens available throughout the entire design system and all consuming applications without restriction. These tokens define the fundamental design vocabulary: the color palette, spacing scale, typography system, and other foundational values.
Local tokens exist within limited scope, typically tied to specific components, features, or contexts. A component’s internal tokens, a feature team’s customization tokens, or context-specific overrides all represent local tokens.
The distinction parallels programming concepts of global and local variables, with similar tradeoffs around accessibility, encapsulation, and change management.
How Global and Local Token Scoping Works
Global tokens form the base layer that everything else builds upon. These tokens are defined centrally, versioned as part of the core design system, and imported by all consumers:
// Global tokens (accessible everywhere)
color.primary: #3B82F6
color.background.default: #ffffff
spacing.md: 16px
typography.body.md: {...}
Local tokens build on global tokens for specific contexts. A component might define local tokens that reference global values:
// Button component local tokens
button.background.default: {color.primary}
button.background.hover: {color.primary.dark}
button.padding.x: {spacing.md}
These button tokens are scoped to the button component’s implementation. They exist to serve the button’s needs and may not be appropriate for other components to reference directly.
CSS custom property scoping provides one mechanism for local tokens on the web:
/* Global tokens on :root */
:root {
--color-primary: #3B82F6;
--spacing-md: 16px;
}
/* Local tokens scoped to component */
.button {
--button-bg: var(--color-primary);
--button-padding: var(--spacing-md);
background: var(--button-bg);
padding: var(--button-padding);
}
The local tokens exist only within the button’s cascade, invisible to unrelated components.
Key Considerations
- Global tokens should represent decisions that genuinely apply everywhere
- Local tokens prevent global namespace pollution
- Changes to global tokens have system-wide impact requiring careful consideration
- Changes to local tokens have contained impact within their scope
- Documentation should clarify token scope and appropriate usage
- Consuming teams should not depend on other teams’ local tokens
- Tooling can enforce scope boundaries through access controls or linting
- Migration from local to global (or vice versa) requires coordination
Common Questions
How should scope decisions be made?
Scope decisions should follow the principle of least privilege: tokens should have the minimum scope necessary for their purpose.
Candidates for global scope include fundamental palette colors, the spacing scale, typography definitions, and other values that genuinely apply across the entire system. If something should look or behave the same wherever it appears, it belongs in global scope.
Candidates for local scope include component-specific customization, feature-specific overrides, and experimental values not ready for system-wide adoption. If something serves a specific context without broader applicability, local scope is appropriate.
Gray areas arise with semantic tokens. Is color.error global or local? If error styling should be consistent system-wide, global scope makes sense. If different contexts handle errors differently, local variants might be appropriate.
When uncertain, starting with local scope is often safer. Promoting a local token to global scope is easier than restricting a global token’s usage.
How do local tokens relate to component encapsulation?
Component encapsulation isolates component internals from external dependencies. Local tokens support encapsulation by keeping component-specific values within the component boundary.
Well-encapsulated components expose deliberate customization points while hiding implementation details. Local tokens can serve as those customization points:
.card {
/* Customization points exposed as local tokens */
--card-background: var(--color-background-surface);
--card-padding: var(--spacing-lg);
--card-border-radius: var(--border-radius-md);
/* Implementation uses local tokens */
background: var(--card-background);
padding: var(--card-padding);
border-radius: var(--card-border-radius);
}
Consumers can override these local tokens to customize the card:
.my-context .card {
--card-background: var(--color-background-elevated);
--card-padding: var(--spacing-md);
}
This pattern exposes intentional flexibility while maintaining encapsulation of how the component implements its styling.
What about tokens that need both global consistency and local customization?
Some design values need system-wide defaults while allowing contextual overrides. This dual requirement can be addressed through layered token definitions.
Global tokens define the default:
color.background.card: {color.background.surface}
Local contexts can override when needed:
.dense-layout {
--color-background-card: var(--color-background-subtle);
}
The global token provides consistency by default, while the override mechanism enables justified exceptions.
Token inheritance through CSS cascade naturally supports this pattern. Global tokens on :root establish defaults. More specific selectors override for particular contexts. Components pick up whichever value applies to their position in the DOM.
Build-time approaches can also support this through theme layers or conditional token compilation that produces context-specific outputs.
Summary
Global and local token scoping determines where tokens are accessible and how changes propagate. Global tokens provide system-wide consistency for foundational values. Local tokens encapsulate context-specific decisions within bounded scope. Making appropriate scoping decisions based on genuine applicability, combined with clear documentation and enforced boundaries, creates token systems that balance consistency with flexibility.
Buoy scans your codebase for design system inconsistencies before they ship
Detect Design Drift Free