Deep Dive: DTCG 1.0 Structured Formats
Why Follow DTCG?
The W3C Design Tokens Community Group (DTCG) 1.0 specification defines a standard format for design tokens that enables interoperability between tools, platforms, and organizations. By following this specification, our tokens work with Figma, Style Dictionary, Tokens Studio, and any other DTCG-compliant tool.
More importantly, DTCG mandates structured object formats instead of simple strings. This enables type safety, platform flexibility, and scalable theming that wouldn't be possible with primitive string values.
Token Anatomy
Every DTCG token is an object with specific properties:
{
"tokenName": {
"$type": "color", // Required: token type
"$value": "#0a65fe", // Required: token value
"$description": "Primary brand blue", // Optional: documentation
"$extensions": { // Optional: custom metadata
"design.paths.dark": "#4d9fff"
}
}
}| Property | Required | Purpose |
|---|---|---|
$type | Yes | Declares the token's data type for validation |
$value | Yes | The token's value (format depends on type) |
$description | No | Human-readable documentation |
$extensions | No | Custom metadata (theming, platform variants) |
DTCG Type System
DTCG defines a fixed set of token types. Each type has specific value format requirements:
| Type | Value Format | Example |
|---|---|---|
color | Hex string or color object | "#0a65fe" |
dimension | Number with unit (px, rem) | "16px" |
number | Unitless number | 1.5 |
duration | Time with unit (ms, s) | "250ms" |
cubicBezier | Array of 4 numbers | [0.4, 0, 0.2, 1] |
fontFamily | String or array of strings | "Inter, sans-serif" |
fontWeight | Number or keyword | 700 or "bold" |
typography | Composite object | See below |
shadow | Composite object | See below |
border | Composite object | See below |
Color Values
Colors can be specified as hex strings or structured objects. We primarily use hex strings for simplicity, but structured objects enable advanced color space support.
Hex String (Simple)
{
"$type": "color",
"$value": "#0a65fe"
}Structured Color Object
For advanced use cases, DTCG supports structured color objects with explicit color space and components:
{
"$type": "color",
"$value": {
"colorSpace": "srgb",
"components": [0.04, 0.4, 0.996]
}
}Modern Color Spaces
Structured objects support modern color spaces like OKLCH for better perceptual uniformity:
{
"$type": "color",
"$value": {
"colorSpace": "oklch",
"components": [0.65, 0.25, 240]
},
"$description": "OKLCH blue - perceptually uniform"
}Color with Alpha
// Hex with alpha
{
"$type": "color",
"$value": "#0a65fe80" // 50% opacity
}
// Structured with alpha
{
"$type": "color",
"$value": {
"colorSpace": "srgb",
"components": [0.04, 0.4, 0.996],
"alpha": 0.5
}
}Dimension Values
Dimensions represent spatial values with units. DTCG 1.0 restricts units to px and rem for consistency.
// Pixel dimension
{
"$type": "dimension",
"$value": "16px"
}
// Relative dimension
{
"$type": "dimension",
"$value": "1rem"
}
// Zero (no unit required)
{
"$type": "dimension",
"$value": "0"
}Dimension vs Number
Use dimension for spatial values that need units. Use number for unitless values like line-height multipliers:
// Dimension: has unit
{
"fontSize": {
"$type": "dimension",
"$value": "16px"
}
}
// Number: unitless multiplier
{
"lineHeight": {
"$type": "number",
"$value": 1.5
}
}Composite Tokens
Complex tokens like typography and shadows combine multiple values into a single token. These are called composite tokens.
Typography Composite
{
"$type": "typography",
"$value": {
"fontFamily": "{core.typography.family.inter}",
"fontSize": "16px",
"fontWeight": 400,
"lineHeight": 1.5,
"letterSpacing": "0em"
},
"$description": "Body text style"
}Shadow Composite
{
"$type": "shadow",
"$value": {
"offsetX": "0px",
"offsetY": "4px",
"blur": "8px",
"spread": "0px",
"color": "#00000014"
},
"$description": "Subtle elevation shadow"
}Border Composite
{
"$type": "border",
"$value": {
"color": "{semantic.color.border.default}",
"width": "1px",
"style": "solid"
},
"$description": "Standard border"
}Token References
Tokens can reference other tokens using the {token.path} syntax. This creates a graph of dependencies that the build system resolves.
// Core token (leaf node)
{
"palette": {
"blue": {
"500": {
"$type": "color",
"$value": "#0a65fe"
}
}
}
}
// Semantic token (references core)
{
"background": {
"brand": {
"$type": "color",
"$value": "{core.color.palette.blue.500}"
}
}
}Reference Resolution
References are resolved at build time. The build system follows the reference chain and substitutes the final value:
// Source
semantic.color.background.brand = "{core.color.palette.blue.500}"
// Resolved
semantic.color.background.brand = "#0a65fe"Extensions for Advanced Features
The $extensions property provides custom metadata for features beyond the DTCG spec. We use it for theming and calculations.
Theme-Specific Overrides
{
"$type": "color",
"$value": "{core.color.palette.neutral.600}",
"$extensions": {
"design.paths.light": "{core.color.palette.neutral.600}",
"design.paths.dark": "{core.color.palette.neutral.300}"
}
}CSS Calculations
{
"$type": "dimension",
"$value": "16px",
"$extensions": {
"design.calc": "calc({core.spacing.size.04} + 2px)"
}
}Pitfalls to Avoid
1. Wrong Type for Value
The $type must match the $value format. Mismatches cause validation errors.
// BAD: Type/value mismatch
{
"$type": "dimension",
"$value": "#0a65fe" // Color value with dimension type!
}
// GOOD: Matching type and value
{
"$type": "color",
"$value": "#0a65fe"
}2. Missing Units on Dimensions
Dimensions require units (except zero). Numbers are for unitless values.
// BAD: Dimension without unit
{
"$type": "dimension",
"$value": "16" // Missing unit!
}
// GOOD: Dimension with unit
{
"$type": "dimension",
"$value": "16px"
}
// GOOD: Zero doesn't need unit
{
"$type": "dimension",
"$value": "0"
}3. Invalid Unit Types
DTCG 1.0 only allows px and rem for dimensions. Other units like em, %, or vh are not valid.
// BAD: Invalid units
{
"$type": "dimension",
"$value": "1em" // em not allowed
}
{
"$type": "dimension",
"$value": "100%" // % not allowed
}
// GOOD: Valid units
{
"$type": "dimension",
"$value": "16px"
}
{
"$type": "dimension",
"$value": "1rem"
}4. Circular References
References cannot form cycles. The validator catches these at build time.
// BAD: Circular reference
{
"primary": { "$value": "{semantic.color.secondary}" },
"secondary": { "$value": "{semantic.color.primary}" }
}
// GOOD: Linear reference chain
{
"primary": { "$value": "{core.color.palette.blue.500}" },
"secondary": { "$value": "{core.color.palette.blue.400}" }
}5. Referencing Non-Existent Tokens
References must point to tokens that exist. Typos in paths cause build failures.
// BAD: Typo in reference
{
"$value": "{core.color.pallete.blue.500}" // "pallete" typo!
}
// GOOD: Correct path
{
"$value": "{core.color.palette.blue.500}"
}Build System Integration
Our build pipeline transforms DTCG tokens into platform-specific formats:
| DTCG Format | CSS Output | TypeScript Output |
|---|---|---|
#0a65fe | #0a65fe | '#0a65fe' |
16px | 16px | '16px' |
250ms | 250ms | '250ms' |
[0.4, 0, 0.2, 1] | cubic-bezier(0.4, 0, 0.2, 1) | [0.4, 0, 0.2, 1] |
| Typography composite | Multiple CSS properties | Typed object |
Summary
- DTCG 1.0 provides a standard format for interoperability
- Every token has
$typeand$value;$descriptionand$extensionsare optional - Colors can be hex strings or structured objects with color space
- Dimensions require units (
px,rem) except for zero - Composite tokens combine multiple values (typography, shadow, border)
- References use
{token.path}syntax and cannot be circular - Extensions enable theming and custom features beyond the spec
Next Steps
Understanding DTCG formats is foundational. From here, explore how the core vs semantic model uses these formats, how schema validation enforces them, and how the build pipeline transforms them into CSS and TypeScript.