Skip to main content
  • Created:
  • Updated:
  • Author:
    Takeshi Takatsudo

Component Tokens & Arbitrary Values

The Problem

When building components with a tight token strategy, teams encounter a recurring question: "The value I need isn't in our token set — should I add a new token?"

This question arises constantly. A button needs to be exactly 28px wide for its icon. A grid layout requires 120px and 1fr columns. A decorative gradient uses a specific red that doesn't match any brand color. If the answer is always "add a token," the token set grows until it's no longer tight — you're back to the unconstrained mess the strategy was designed to prevent.

But if the answer is always "use only existing tokens," developers are forced to use poorly fitting values, creating visually awkward components. Neither extreme works. The missing piece is a clear framework for deciding when a value belongs in the system and when it belongs in the component.

The Solution

The tight token strategy is built on a component-centric philosophy. This aligns closely with Tailwind CSS's own approach:

  1. Design tokens define the system vocabulary — spacing, colors, typography scales that ensure consistency across all components
  2. Components are built using those tokens — for all standard, reusable spacing and colors
  3. But not everything fits into the system — component-specific details use arbitrary values

The key insight: adding a token is a system-level decision, not a component-level one. When a particular value is unique to a single component's layout or decoration, it should stay as an arbitrary value (Tailwind's bracket syntax like w-[28px]), not be promoted to the token set.

When to Use Arbitrary Values

Use Tailwind's bracket syntax for values that are structural details of individual components, not system-wide patterns:

  • Component-specific sizing — A small icon button that needs exactly w-[28px] p-[6px] for visual balance
  • Grid template columns — Layouts like grid-cols-[120px_1fr] that define one component's structure
  • Unique icon dimensions — An icon sized to w-[18px] for optical alignment within its context
  • One-off decorative values — A gradient from-[hsl(0_60%_20%)] to-[hsl(0_60%_8%)] used only in one hero section
  • Mathematically calculated values — Offsets like top-[calc(100%-2px)] for precise positioning

When to Use System Tokens

Use tokens from the project's @theme definition for values that represent shared design decisions:

  • Standard component spacingpx-hsp-sm py-vsp-xs for card padding, section margins
  • Colors with semantic meaningbg-primary text-text-muted for brand and text
  • Gaps between repeated elementsgap-x-hsp-xs gap-y-vsp-sm for grids and flex layouts
  • Any value referenced by name in design specs — If a designer says "use section gap," that's a token

Decision Framework

When deciding between a token and an arbitrary value, use this decision tree:

SituationAction
Value is reused across multiple componentsAdd a system token
Value is semantically meaningful (e.g., "section gap")Add a system token
Value is unique to one componentUse arbitrary value
Value is mathematically calculated or decorativeUse arbitrary value
Unsure whether it's a system concernStart with arbitrary, promote to token later if reused

Signs You Should Add a Token

  • Multiple components use the same arbitrary value
  • A designer references the value as a named spacing or color step
  • The value represents a semantic concept, not just a pixel number
  • Changing this value should update the entire system, not one component

Signs You Should NOT Add a Token

  • It's used in exactly one place
  • It's a structural or layout detail specific to one component
  • Adding it would clutter the token set without adding clarity
  • The value has no meaning outside its component context

Demos

System Tokens Mixed with Arbitrary Values

This card component uses system tokens for its standard spacing and colors, but arbitrary values for its component-specific grid layout and decorative icon sizing. Comments show which values come from the token system and which are arbitrary.

System Tokens + Arbitrary Values in a Component

In the code, system tokens appear where the value follows the project's spacing vocabulary — hsp-sm (20px) for horizontal padding, vsp-xs (8px) for vertical padding, hsp-xs (12px) for gaps. Arbitrary values appear for component-specific details: the icon is 18px for optical balance, the grid uses 120px for its sidebar width, and the stat number uses 22px for visual impact. None of these arbitrary values belong in the system token set because they're meaningful only inside this component.

Token Promotion: Before and After

When the same arbitrary value keeps appearing across components, it's a signal to promote it to a system token. This demo shows a pricing layout where a frequently-used card width has been promoted from an arbitrary value to a named token.

Before and After Token Promotion

In the "before" version, three developers each picked slightly different padding and font sizes for the same pricing card component. The cards look subtly uneven — 18px vs 14px vs 16px vertical padding, 28px vs 32px vs 26px price font size. Once the team noticed this pattern recurring across pricing, feature cards, and testimonial cards, they promoted the values to system tokens: vsp-sm / hsp-sm for padding and heading for the price font size. Now every card automatically stays consistent.

Mixing System Tokens and Arbitrary Values in a Real Layout

This demo simulates a realistic component from a production project. System tokens handle all the standard spacing, colors, and typography. Arbitrary values handle the component-specific layout grid and decorative details.

Production Component: Tokens + Arbitrary Values

In a real Tailwind project, this component's classes would look like:

<!-- System tokens for standard spacing and colors -->
<section class="px-hsp-sm py-vsp-sm">
<!-- ARBITRARY for component-specific grid layout -->
<div class="grid grid-cols-[80px_1fr] gap-x-hsp-sm">
<!-- ARBITRARY for avatar dimensions -->
<div class="w-[64px] h-[64px] rounded-full" />
<div class="flex flex-col gap-y-vsp-2xs">
<!-- System tokens for tag spacing -->
<span class="px-hsp-xs py-vsp-2xs bg-success/10 text-success">Active</span>
</div>
</div>
</section>
<!-- ARBITRARY for icon button, system tokens for primary button -->
<button class="w-[32px] h-[32px] p-[6px]">Edit</button>
<button class="px-hsp-sm py-vsp-xs bg-primary text-text-inverse">View Profile</button>

Common AI Mistakes

Mistake 1: Creating Tokens for Every Value

<!-- BAD: Polluting the token set with one-off values -->
<!-- Adding --spacing-avatar: 64px to @theme is wrong -->
<div class="w-avatar h-avatar" />

<!-- GOOD: Use arbitrary for component-specific sizes -->
<div class="w-[64px] h-[64px]" />

One-off values clutter the token set. A 64px avatar size is meaningful only within the profile component. If it were promoted to a token, other developers might use it for unrelated purposes, diluting its intent.

Mistake 2: Using Arbitrary Values for Everything

<!-- BAD: Ignoring system tokens entirely -->
<div class="p-[20px] gap-[12px] bg-[hsl(221_83%_53%)]">

<!-- GOOD: Use system tokens for shared design values -->
<div class="px-hsp-sm gap-x-hsp-xs bg-primary">

If a value exists in the token set, always use the token. Arbitrary values should only appear when the token set genuinely doesn't cover the need.

Mistake 3: Adding Tokens Preemptively

<!-- BAD: Adding --spacing-icon-sm: 18px because "we might need it" -->
<!-- GOOD: Start with w-[18px], promote to token only if reused -->

The "promote later" approach prevents token bloat. If 18px icon sizing shows up in 5 components, that's a clear signal to add --spacing-icon-sm: 18px to the theme. Until then, keep it arbitrary.

When to Use

This component-centric approach applies whenever you work with the tight token strategy:

  • Building new components — Default to system tokens for spacing and colors, use arbitrary for layout-specific details like grid columns, icon sizes, and decorative values
  • Reviewing component code — Check that arbitrary values are truly one-off and system tokens are used for shared values
  • Growing the token set — When the same arbitrary value appears in 3+ components, promote it to a named token
  • Refactoring existing components — Look for hardcoded values that match existing tokens and replace them

The goal is a token set that stays small and meaningful. Every token should earn its place by being genuinely reusable across the system. Everything else stays at the component level as an arbitrary value.