Size & spacing
Control height, surrounding space, and vertical rhythm are related decisions with separate jobs. Set the shared family once, then use component size and layout props to compose it.
Follow a control height
With an explicit 16px text base and a size ratio of 1.2:
| Decision | Small | Medium | Large |
|---|---|---|---|
Control roominess 2.5 | About 33.3px | 40px | 48px |
Control roominess 2.75 | About 36.7px | 44px | 52.8px |
The relationship is medium = base text size × roominess, small = medium ÷ size ratio, and large = medium × size ratio. These values describe the shared height roles. Content, borders, and component-specific constraints can still require more room.
text-size: 16px control-roominess: 2.75
↘ ↙
medium: 44px
↙ ↘
small: 44 ÷ 1.2 large: 44 × 1.2A 44px example is the result of these chosen values. Choose the proportions appropriate to your interface. Touch-target area is a separate decision and can extend beyond a compact visible control where neighboring controls allow it.
Map your decisions
| Recipe key | CSS property | What changes |
|---|---|---|
control-roominess | --ui-control-roominess | Medium control height as a unitless multiple of the text base. Derives --ui-control-size and its small, medium, and large roles. |
scale-contrast | --ui-scale-ratio | The separation between sizes. At 1, the control sizes are equal; higher ratios separate them. |
rhythm | --ui-rhythm | Vertical Stack gaps and unitless line-height multipliers. Horizontal navigation and action-row gaps retain their own spacing. |
spacing | --ui-spacing | Gaps and padding independently of control heights and text ratios. |
space-curve | --ui-space-curve | How the spacing scale grows. 1 is linear; increasing toward 2 curves the intermediate steps while keeping stable endpoints. |
corner-roundness | --ui-radius-md | The shared corner family for controls and surfaces. |
line-weight | --ui-border-width | Shared border weight. Focus visibility has its own roles. |
Keep height and space distinct
If buttons and fields feel too tall, change Control roominess. If content feels crowded around otherwise well-proportioned controls, change Spacing. If stacked paragraphs and groups need more vertical breathing room, change Rhythm.
{
"schemaVersion": 1,
"values": {
"text-size": "16px",
"control-roominess": "2.75",
"scale-contrast": "1.2",
"spacing": "1.1",
"rhythm": "1.1"
}
}In component markup, use supported props such as size="sm" on a control or gap="l" on Stack. Let the theme supply the shared values behind those choices.
Preserve units
Base text-size is px-only and sets the document root. Other supported length inputs retain their CSS units, including rem, with generated guards for their documented bounds. Set the base on :root; a nested light/dark region shares that rem root.
For older recipes, replace density with spacing. Replace a length-valued control-size with numeric control-roominess by dividing the desired medium height by the original text base. For example, 40px ÷ 16px becomes 2.5.