Flexible density for all the UI

In our UI system we dont use pixel values to define spacing, we use semantic variables, (t-shirt sizes: gap-sm, p-lg, my-2xl) - so thats like you change one CSS variable, and the whole UI adapts.
We limit user customization to just 5 presets - 0.8 / 0.9 / 1 / 1.1 / 1.2:
Symmetric around 1.0 - two steps down, two up;
±20% is deliberately restrained - enough to change the feel (data-dense ↔ spacious) without breaking layouts or distorting proportions;
5 discrete stops = perceptible but decision-light. Most users never open the control, so it's a coarse preference, not a fine instrument
The biggest reason why do we have it - to support bigger themes differentiation. Brand-overlay density has slightly bigger range: 0.7–1.35; so we can differentiate brands providing customizable UI: >1 reads editorial/airy, <1 terminal/dense. Same components, different feel — no fork. The user can always override.
/* Density cascade: user override → brand default → system default (1) */
--density: var(--user-density, var(--brand-density, 1));
Everything is built on a 4px base unit and a single --density variable, all declared in :root:
--unit: 0.25rem;
/* Every spacing token is base-step × unit × density */
--space-xs: calc(2 * var(--unit) * var(--density, 1)); /* 8px @ d=1 */
--space-sm: calc(4 * var(--unit) * var(--density, 1)); /* 16px */
--space-md: calc(6 * var(--unit) * var(--density, 1)); /* 24px */
--space-lg: calc(8 * var(--unit) * var(--density, 1)); /* 32px */
--space-xl: calc(12 * var(--unit) * var(--density, 1)); /* 48px */
--space-2xl: calc(16 * var(--unit) * var(--density, 1)); /* 64px */
--space-3xl: calc(24 * var(--unit) * var(--density, 1)); /* 96px */
--space-4xl: calc(32 * var(--unit) * var(--density, 1)); /* 128px */
--space-5xl: calc(40 * var(--unit) * var(--density, 1)); /* 160px */
But those are details, the main point was to have flexible spacing underneath so all the UI is adaptable to any vibe.
Also if we talk about accessibility - minimum control height is preserved, different for touch screens:
--size-touch-min: 2.75rem; /* 44px — coarse/touch base (scales with density) */
--control-height-min: 2.25rem; /* 36px — coarse floor (hard min) */
@media (pointer: fine) {
--size-touch-min: 2.25rem; /* 36px — fine/mouse base */
--control-height-min: 2rem; /* 32px — fine floor */
}
--control-height: max(var(--control-height-min), calc(var(--size-touch-min) * var(--density)));
44px touch base = the WCAG 2.5.5 / Apple HIG / Material touch-target minimum — a finger needs ~44 CSS px.
36px desktop base = the 2026 SaaS convention (Linear / Vercel / shadcn / Notion); a mouse is precise, so desktop controls can be denser than touch.
The floors exist because controls, unlike spacing, cant shrink freely. Spacing tokens have no floor (Compact just scales them down). Controls are clamped by max() so Compact density (0.8×) can't shrink a button into an un-hittable size: 44×0.8 = 35.2 → 36 on touch, 36×0.8 = 28.8 → 32 on desktop. That asymmetry (whitespace compresses without limit, hit-targets don't) is the whole point of the floor.
The floor is a separate variable from the base so Compact can legally drop below the standard (desktop 36 → 32) while still being bounded. If the floor equalled the base, density could never push a control under its standard size at all.




