Spacing
The spacing unit, what Density changes, and which gap to use for which purpose.
Unit
One step is 0.25rem times Scaling — 4px at a 16px root and 100% scaling. Every numeric
utility (gap-2, p-4, …) counts in steps, so gap-2 is 8px. Scaling (data-scaling)
zooms every step; Density does not touch it.
Density
Density is the spacing prop on Theme (data-spacing). It changes only the
layout gap, the space between components in layout and collection primitives:
data-spacing | Layout gap |
|---|---|
dense | 0.8 × step |
default | 1 × step |
roomy | 1.2 × step |
A component's own padding, control sizes, and inner gaps stay fixed when Density changes.
The rule
Decide by what is spaced, not where it sits:
- Independent siblings — items of a collection, stacked fields, page sections: use the
layout gap,
gap-[calc(var(--spark-layout-gap)*N)], so the space follows Density. Fields inside a card or dialog are still siblings. - Parts of one composed unit — icon to label, title to description, media to text, a
surface's header, body and footer: use a numeric step (
gap-1,gap-2, …), so the unit looks the same at every Density.
Prefer the component in "Set by" that already sets the gap; hand-write the calc only when none fits.
Figma names four tiers. Elements are parts of one unit and stay fixed when Density
changes: gap-1 (0.25rem) for a close relationship, gap-2 (0.5rem) for a hierarchical one,
such as a heading above its text. Blocks are independent siblings and follow Density:
layout gap × 4 (1rem) for a closer relationship, × 8 (2rem) for a loose one. Sizes are at
default Density and 100% Scaling; Scaling zooms all four. 1rem between parts of one surface
is gap-4, an element gap, fixed.
Which gap for which purpose
The table lists purposes, not components; a component's own gap may differ.
| Purpose | Gap | Tier | Set by |
|---|---|---|---|
| a header's title above its description | gap-2 | Elements, hierarchical | Dialog, Drawer, Sheet, AlertDialog, EmptyState, Callout, EnergyBreakdown |
| title over one muted line in a compact row | gap-1 | Elements, close | Field, List, EntityCard, Toast, ScheduleList, StatCard |
| icon to label in a small control | gap-1 | Elements, close | |
| icon to label in a control; parts of a compact unit | gap-2 | ||
| media to text in a compact row or header | gap-3 | ||
| groups inside one surface (card, dialog, empty-state body) | gap-4 | ||
| items of a list, or of a soft accordion or toggle group | layout gap × 0.5 | List, Accordion (soft), ToggleGroup (soft) | |
| cards in a group | layout gap × 2 | RadioCardGroup | |
| radios in a group | layout gap × 3 | RadioGroup | |
| fields, page sections | layout gap × 4 | Blocks, closer | FieldSet, FieldGroup, PageContainer |
| loosely related sections | layout gap × 8 | Blocks, loose | MessageScroller |
The one exception: Table row height is layout gap × 10, because a row is the space between
items of a collection (see Theme).
Padding is not covered here.