Edit a shared spacing token and see its consumers update together.
This demonstration uses direct Spacing to show the base scale: these paddings and gaps intentionally keep a stable value across breakpoints. Prefer Density when building ordinary component spacing.
The colored areas below use the page’s actual CSS variables. Edit space(4) to update both boxes and the gap between the action items.
padding: space(4)padding: space(4)gap: space(4)These edits update the playground’s custom theme and persist spacing overrides in this browser when storage is available. Other UI using the token may also change. They do not write to your source JSON file. The reference examples above stay unchanged.
Each ring shows a spacing level measured from the same content. These are alternative distances, not nested paddings added together. Click a ring to edit its token, or use the labeled token fields below. Custom values determine ring size; token numbers alone do not guarantee size order.
.any-class {
padding: space(4);
}Spacing defines a value; Density defines how spacing responds to the viewport. Prefer density(n) for component spacing using the theme’s responsive mapping. Use space(n) directly when a stable value across breakpoints is intentional. Changing that mapping updates every consumer of the token without changing component code.
Density is the recommended default for component spacing. Standard CSS remains available when finer control is needed. The generated media queries belong to the system; they are not removed from CSS.
UXDSL builds on standard CSS. Spacing defines the base spacing values, and Density makes that spacing responsive. Prefer Density for component spacing, use Spacing when a stable value is intentional, and use CSS directly when finer control is needed. This is the recommended authoring approach, not a compiler restriction.
A Density token maps a level to spacing values at different breakpoints. The 4 in density(4) identifies a token; it does not mean four pixels or a multiplier. You define its progression.
This example is a theme excerpt. Density reuses the spacing scale instead of introducing a separate set of measurements.
{
"breakpoints": { "xs": 0, "md": 768, "xl": 1280 },
"spacing": {
"4": "0.75rem",
"5": "1rem",
"6": "1.5rem"
},
"densities": {
"4": "xs(space(4)) md(space(5)) xl(space(6))"
}
}| Viewport | density(4) | space(4) |
|---|---|---|
| Below 768px | space(4) → 0.75rem | 0.75rem |
| 768–1279px | space(5) → 1rem | 0.75rem |
| 1280px and above | space(6) → 1.5rem | 0.75rem |
A rule remains active until another defined breakpoint overrides it. The progression is configurable: spacing can increase, decrease or stay the same.
.card, .panel {
padding: density(4);
}The card and panel choose a token. Its responsive behavior lives in the theme.
/* Base spacing tokens from the theme */
:root {
--uxdsl__space__4: 0.75rem;
--uxdsl__space__5: 1rem;
--uxdsl__space__6: 1.5rem;
--uxdsl__density__4: var(--uxdsl__space__4);
}
@media (min-width: 768px) {
:root { --uxdsl__density__4: var(--uxdsl__space__5); }
}
@media (min-width: 1280px) {
:root { --uxdsl__density__4: var(--uxdsl__space__6); }
}
.card, .panel {
padding: var(--uxdsl__density__4);
}You can build this same behavior in plain CSS using responsive custom properties. UXDSL generates those rules from the theme, so you maintain one mapping instead of repeating breakpoint decisions in each component. Less repeated source code does not necessarily mean less generated CSS.
These live boxes use this page’s current theme and actual browser viewport. The colored area is padding. Edit the active rule for Density 4 to see both responsive boxes change; the fixed box continues to use space(4).
Live density(4): xs(space(4)) md(space(5)) xl(space(6))
padding: density(4)padding: density(4)padding: space(4)Resize your browser to see the responsive boxes follow the mapping. The JSON and CSS above remain a reference example; the live definition shows your edits. Edits are a local demo and are not saved to your theme file.
Two ways to update the system: change a spacing value to update every reference to that spacing token, or change a Density mapping to update every consumer of that Density token. Component declarations stay the same.
Prefer density() for component spacing. Use space() directly for an intentional stable value, or CSS for finer control. A Spacing value remains editable through the theme. Density coordinates spacing; layout changes such as columns and navigation still need their own responsive decisions.
Each ring compares a Density level measured from the same content. The rings are not nested component paddings added together. Click a ring to edit its token. This diagram responds to the main browser viewport.
.any-class {
padding: density(4);
}Theme uxdsl.theme.json, merged over the base theme
{
"spacing": {
"4": "0.75rem",
"5": "1rem",
"6": "1.5rem"
},
"densities": {
"4": "xs(space(4)) md(space(5)) xl(space(6))"
}
}UXDSL you write example.uxdsl
.card { padding: density(4); }
.toolbar { gap: space(4); }CSS you get compiled by uxdsl; :root shows only these tokens
:root {
--uxdsl__space__4: 0.75rem;
--uxdsl__space__5: 1rem;
--uxdsl__space__6: 1.5rem;
}
:root { --uxdsl__density__4: var(--uxdsl__space__4); }
@media (min-width: 768px) { :root { --uxdsl__density__4: var(--uxdsl__space__5); } }
@media (min-width: 1280px) { :root { --uxdsl__density__4: var(--uxdsl__space__6); } }
.card { padding: var(--uxdsl__density__4); }
.toolbar { gap: var(--uxdsl__space__4); }UXDSL builds on standard CSS. Spacing defines the base spacing values, and Density makes that spacing responsive. Prefer Density for component spacing, use Spacing when a stable value is intentional, and use CSS directly when finer control is needed. This is the recommended authoring approach, not a compiler restriction.
space(k) is one step of the scale, the same at every width. density(k) is a step the theme moves at breakpoints — the base theme’s density(4) is space(4), then space(5) from md, then space(6) from xl.density(2.5) is UXD_TOKEN_KEY, an undefined key is UXD_DENSITY_REFERENCE / UXD_SPACE_REFERENCE with the keys that exist.padding: xs(space(4)) md(space(5))): the component stops following the theme. Change the density in the theme and every consumer follows.space(0) and density(0) are an explicit zero. Spacing values are rem by default, so they still follow the root font size.spacing["4"] changes direct space(4) uses and every density, radius or typography value that references it; changing densities["4"] changes only density(4) uses..card { padding: density(4); }
.toolbar { gap: space(2); }
.card { padding: density(2.5); } /* UXD_TOKEN_KEY: a key is a name, not a number to scale */The guides for coding agents are on For AI agents.