# Spacing

The spacing scale and the functional layout, content and control roles.

Choose spacing by the relationship between elements: layout organizes independent blocks, content connects parts of one block, and control spacing separates associated actions. Inline and block refer to writing axes, independently of the CSS display type.

## Spacing scale

The shared scale is calculated from `--space-unit`, independently of typography. Its eight steps use multipliers 1, 2, 3, 4, 6, 8, 12 and 16. Functional tokens select these steps for a shared role; component-specific spacing can use the scale directly. Zero and layout keywords such as auto need no token.

| Token          | Role                                                  |
| -------------- | ----------------------------------------------------- |
| `--space-unit` | Base unit from which the spacing scale is calculated. |
| `--space-1`    | Step 1 of the shared spacing scale.                   |
| `--space-2`    | Step 2 of the shared spacing scale.                   |
| `--space-3`    | Step 3 of the shared spacing scale.                   |
| `--space-4`    | Step 4 of the shared spacing scale.                   |
| `--space-5`    | Step 5 of the shared spacing scale.                   |
| `--space-6`    | Step 6 of the shared spacing scale.                   |
| `--space-7`    | Step 7 of the shared spacing scale.                   |
| `--space-8`    | Step 8 of the shared spacing scale.                   |

Change the unit on `:root` to adjust the whole scale. A descendant override does not recompute inherited steps or functional aliases; for a local composition, override the relevant functional token instead. This is a spacing rhythm, not a universal geometric grid: strokes, cross clearances, icon drawings and `Page`'s viewport clearance remain independent. Do not reconstruct arbitrary legacy values as unit multipliers.

## Functional spacing

Choose a role by the relationship between the elements, then padding for an inset or gap for a separation. Each role has an inline and a block axis; they share one value today so that a later design can adjust one axis, such as narrower horizontal insets on phones.

| Token                      | Role                                                                                                  |
| -------------------------- | ----------------------------------------------------------------------------------------------------- |
| `--layout-padding-inline`  | Inline inset from the frame's edges; the gutter that aligns sections and the shell.                   |
| `--layout-padding-block`   | Block inset inside sections and the shell.                                                            |
| `--layout-gap-inline`      | Inline separation between independent blocks.                                                         |
| `--layout-gap-block`       | Block separation between independent blocks.                                                          |
| `--content-padding-inline` | Inline inset inside a contained surface, such as a card or panel.                                     |
| `--content-padding-block`  | Block inset inside a contained surface.                                                               |
| `--content-gap-inline`     | Inline separation between related parts of one block.                                                 |
| `--content-gap-block`      | Block separation between related parts of one block.                                                  |
| `--control-padding-inline` | Inline inset of buttons, fields and other text controls.                                              |
| `--control-padding-block`  | Block inset of buttons, fields and other text controls.                                               |
| `--control-gap-inline`     | Inline separation within a control group: a control and what it carries, or controls acting together. |
| `--control-gap-block`      | Block separation within a control group.                                                              |

### Choose the role

- `layout`: independent blocks, or the frame around them. Sections and their inset, an article beside a sidebar, `Header` and `Footer` insets.
- `content`: related parts of one block. The title, text and footer of a card; paragraphs; the fields of a form.
- `control`: a control with what it carries, or controls acting together. A label, its field and its help; a row of buttons; the options of a fieldset.
- Components own their inset; parents own the separation between children. `.stack`, `.row` and `.formatted` add no container padding.
- `Section` owns outer spacing and defaults to layout gaps. Jointive layouts keep zero gap: `Grid` owns cell boundaries and each cell's content owns its inset. Page margins remain internal to `Page`.

### Local exceptions

Some spacing is not a relationship between elements; it stays in the owning component, using the `--space-*` scale. Keep these cases local rather than forcing a role:

- Lists of destinations, such as navigation links and tabs.
- The internal arrangement of one control, such as the distance between a button's label and its arrow.
- Drawing geometry and optical adjustments, such as the theme switch capsule or a centered touch target.
- Short pairings inside reading content, such as a caption under an image.
- Table cells, which are slots in a dense grid rather than contained surfaces.

### Compose and override

Use component defaults, a named preset or the [stack and row classes](stack-and-row.md) before writing spacing by hand.

```svelte
<script>
  import { Section, Heading } from "@dg/ui";
</script>

<Heading title="Collection" />
<Section padding="no-bottom">
  <p>Content aligned with the frame.</p>
</Section>
<Section gap="content">
  <p>Related content.</p>
  <p>Another related part.</p>
</Section>
```

When writing CSS by hand, inline is horizontal and block is vertical. The two-value `gap` shorthand takes the row gap first: write the block token, then the inline token. Margins and paddings use the token of their own logical axis.

```css
.collection {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
  gap: var(--layout-gap-block) var(--layout-gap-inline);
}

.actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--control-gap-block) var(--control-gap-inline);
}
```
