Skip to content

Object Variable

An object variable groups key-value pairs under a single name. The syntax is one; but it is used for two different purposes:

  • CSS property object — keys are CSS property names, full expansion can be done with var(--obj)
  • Token object — keys are custom token names, always accessed with var(--obj.key)

The compiler handles both the same way. The distinction is in the purpose of the key contents.


Defined with the --name: { key: value; key: value; }; syntax.

/* CSS property object */
--cardBase: { color: #fff; font-size: 16px; };
/* Token object */
--colors: { brand: #2060ff; muted: #6b7280; surface: #f4f6fb; };

Keys consist of valid CSS property names. All properties of the object are expanded to where it is called with var(--obj).

--cardBase: { color: #1a1a2e; font-size: 16px; padding: 16px; };
.card {
var(--cardBase);
margin: 8px;
}

Generated CSS:

.card {
color: #1a1a2e;
font-size: 16px;
padding: 16px;
margin: 8px;
}

A specific key of the object can also be accessed:

--cardBase: { color: #1a1a2e; font-size: 16px; padding: 16px; };
.card-compact {
color: var(--cardBase.color);
font-size: var(--cardBase.fontSize);
}

Generated CSS:

.card-compact {
color: #1a1a2e;
font-size: 16px;
}

CSS property objects can also be used with nested blocks:

--primary: #2060ff;
--cardBase: { color: #fff; font-size: 16px; };
.card {
var(--cardBase);
.title {
color: var(--primary);
}
.body {
font-size: 14px;
}
}

Generated CSS:

:root {
--primary: #2060ff;
}
.card {
color: #fff;
font-size: 16px;
}
.card .title {
color: var(--primary);
}
.card .body {
font-size: 14px;
}

In this example var(--cardBase) does full expansion inside the parent block; nested selectors come out as normal child selectors.


Keys are custom token names, not CSS property names. For this type of object, full expansion with var(--obj) should not be done — it produces invalid CSS. It must always be accessed with var(--obj.key) syntax.

--colors: { brand: #2060ff; muted: #6b7280; surface: #f4f6fb; };
.btn {
background: var(--colors.brand);
color: var(--colors.surface);
}
.label {
color: var(--colors.muted);
}

Generated CSS:

.btn {
background: #2060ff;
color: #f4f6fb;
}
.label {
color: #6b7280;
}

camelCase and kebab-case are cross-resolved in key access. Both access forms work regardless of which form you used in the definition.

Written in definitionAccess form
font-sizevar(--obj.fontSize)
lineHeightvar(--obj.lineHeight)
border-radiusvar(--obj.borderRadius)
--typography: { background: #acacac; lineHeight: 1.5; letter-spacing: 0.01em; };
.body-text {
background: var(--typography.background);
line-height: var(--typography.lineHeight);
letter-spacing: var(--typography.letterSpacing);
}

Generated CSS:

.body-text {
background: #acacac;
line-height: 1.5;
letter-spacing: 0.01em;
}

Keys can also be numbers or a mix of number and letter.

--tone: { 100: #f8faff; 200: #dbe9ff; 900: #0a1628; };
.bg-light {
background: var(--tone.100);
}
.bg-dark {
background: var(--tone.900);
}

Generated CSS:

.bg-light {
background: #f8faff;
}
.bg-dark {
background: #0a1628;
}

Alphanumeric keys like 200a, 2xl are also supported:

--space: { 1: 4px; 2: 8px; 2xl: 24px; };
.gap-2xl {
gap: var(--space.2xl);
}

Key generation inside object body with @for is also possible:

--factor: 2;
--range: [1-4];
--spacing: {
@for(i, var(--range)) {
${i}: ${i * var(--factor)}px;
}
};
.space-2 {
margin: var(--spacing.2);
}

Generated CSS:

.space-2 {
margin: 4px;
}

The same dot access syntax applies to object items inside an array variable.

--breakpoints: [
{ name: sm; size: 640px },
{ name: md; size: 768px }
];
.container {
max-width: var(--breakpoints[0].size);
}

Generated CSS:

.container {
max-width: 640px;
}

CSS Property ObjectToken Object
Key contentCSS property nameCustom token name
var(--obj) full expansion✓ Valid✗ Produces invalid CSS
var(--obj.key) access✓ Valid✓ Valid
Typical usageShared style setDesign tokens (colors, spacing…)