Maple
⌘K
DOCUMENTATIONv2.0.17

Variable Utilities

Define CSS variables directly in class names. Variable utilities make tokens, themes, component variants, and interactive values available exactly where they are needed.

Syntax

A utility variable starts with a CSS custom property name and uses the equal sign to assign its value. Underscores become spaces inside the generated value, and bracket syntax can protect special characters.

Pattern
Generated CSS
--primary=blue
--primary: blue
--gap=1rem_2rem
--gap: 1rem 2rem
--curve=cubic-bezier(0.16,1,0.3,1)
--curve: cubic-bezier(0.16,1,0.3,1)
@dark:--primary=cyan
@media (prefers-color-scheme: dark) { ... }
Variables Are Regular Utilities
Variable utilities can use the same media query, container query, parent, self, and child selector prefixes as any other Maple class. That means a component can own both its tokens and the states that modify them.

Scoped Tokens

Variables inherit through the DOM, so a token defined on a wrapper is available to every child inside it. This is the easiest way to create component-level themes without writing a separate CSS selector.

Coral Scope

Every primary utility class reads the local token.

Violet Scope

The markup stays the same; the token changes.


<div class="--primary=coral">
  <button class="bgc-primary-100 br brc-primary-300 c-primary-700">Save</button>
</div>

<div class="--primary=violet">
  <button class="bgc-primary-100 br brc-primary-300 c-primary-700">Save</button>
</div>

Global Tokens

Add variables to the html element when the entire application should share the same design tokens. Utilities then read those values through Maple's fallback chains.


<html class="
  --primary=blue @dark:--primary=lightblue
  --spacer=0.35
  --rad-lg=12px
">
  <body>
    <button class="bgc-primary-100 c-primary-600 p-4 rad-lg">
      Global tokens
    </button>
  </body>
</html>
SPAs and MPAs
For single-page apps, global variable utilities can remove the need for a separate token stylesheet. For multi-page apps, a cached CSS file may be more efficient when the same tokens are repeated across many documents.

Fallback Chains

Hyphen utilities resolve through variables before falling back to their raw value. This lets one token serve many utilities, while property-specific variables can override a token only where needed.

Class
Resolution Order
c-primary
--c-primary -> --color-primary -> --primary

Text color can have its own override. See Color Resolution

bgc-primary
--bgc-primary -> --color-primary -> --primary

Background color can share or override the same token. See Color Resolution

p-card
--p-card -> --space-card -> --card

Spacing tokens can be semantic instead of numeric. See Number Resolution

ff-mono
--ff-mono -> --mono

Any token can be defined on any selector. See Custom Resolution

Base scope

All colors and spacing are based on primary and space-card scoped variables.

Property-specific overrides

Background color, text color, and padding are overridden with bgc-primary, c-primary, and p-card scoped variables.


<div class="--primary=olive --space-card=2.5rem">
  <div class="bgc-primary-100 br brc-primary-300 c-primary-500 p-card">
    Base scope
  </div>

  <div class="--bgc-primary=tomato --c-primary=peru --p-card=1.5rem">
    <div class="bgc-primary-100 br brc-primary-300 c-primary-500 p-card">
      Property-specific overrides
    </div>
  </div>
</div>

State and Media Variables

Change variables instead of repeating long sets of utilities. The child utilities stay stable, while parent, hover, breakpoint, or color-scheme selectors update the tokens they consume.

Hover token Hover the button to change one variable.
Color-scheme token Dark mode can change the same utility output.

<!-- Self selector -->
<button class="--primary=gray &:hover:--primary=aqua bgc-primary-100 c-primary-700">
  Hover me
</button>

<!-- Media query -->
<section class="--primary=coral @dark:--primary=aqua">
  <div class="bgc-primary-100 c-primary-900">Theme-aware content</div>
</section>

<!-- Breakpoint -->
<div class="--space-card=1rem md:--space-card=2rem p-card">
  Responsive padding
</div>

Dynamic Variables

Use the $$ prefix for values that change frequently, such as slider values, pointer coordinates, or scroll-driven values. Dynamic classes are written to Maple's ephemeral layer so the main stylesheet does not collect a new permanent rule for every value.


const slider = document.getElementById('slider');
const preview = document.getElementById('preview');

slider.addEventListener('input', (event) => {
  const value = event.target.value;

  preview.classList.add(`$$--p-spacer=${value}`, `$$--g-spacer=${value}`);
});

slider.addEventListener('change', (event) => {
  const value = event.target.value;

  preview.classList.add(`--p-spacer=${value}`, `--g-spacer=${value}`);
});
ESC

Start typing to search across the documentation.