> ## Documentation Index
> Fetch the complete documentation index at: https://docs.graphy.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Layout

The engine stacks the title, legend, axes, plot and footer. `gap` is the space between items *inside* a chrome target (pills in a legend, cards in a headline). `margin` is the air *around* a chrome target that occupies a layout slot. `padding` is the frame. Position of the legend still lives on `config.legend`. Two neighbouring keys also change how much room the chart needs, so they're covered here too: `panel.overflow` and `style.graph({ textScale })`.

```tsx theme={null}
style.graph({ padding: 32 });
style.header({ margin: { bottom: 10 } });
```

## Padding

<ParamField path="style.graph.padding" type="number | { top?: number; right?: number; bottom?: number; left?: number }" default="24">
  Outer padding in pixels, authored on `style.graph`. A number applies to all four sides; an object
  (`{ top?, right?, bottom?, left? }`) sets sides individually. Omitted edges keep the builtin 24.
</ParamField>

Any side you leave out of the object form keeps the 24px default, so this trims the left edge and
opens up the top while the other two stay put:

```tsx theme={null}
style.graph({ padding: { top: 40, left: 0 } });
```

An explicit `0` removes a side's padding. Padding is measured in pixels and does not scale with `textScale`.

## Margin

Air around a chrome target that occupies a layout slot lives on that target's `margin`. Values are pixels and do not follow `textScale`. A number sets every side. An object sets CSS edges; omitted sides stay absent so they do not overwrite earlier rules. `0` closes a side.

```tsx theme={null}
style.header({ margin: { bottom: 10 } });
style.legend({ gap: 8, margin: 10 });
style.axisLabel.bottom({ margin: { top: 4, bottom: 16 } });
```

When two boxes meet, the larger margin wins. A box the chart does not draw contributes none. A margin that faces the frame sits next to `style.graph({ padding })`.

`style.legend`, `style.axisLabel` and `style.tickLabel` take `.top` / `.right` / `.bottom` / `.left` (and still take `.x` / `.y`). A bare call covers every instance; a later match wins.

| Target | What `margin` spaces |
| - | - |
| `header` | The title + subtitle row |
| `footer` | Caption, source and provenance |
| `legend` | A pill legend (`gap` is still items inside) |
| `headline` | The headline strip |
| `axisLabel` | An axis title. `.left` / `.right` do not feed layout |
| `tickLabel` | The tick band. `offset` stays; ticks have no builtin margin |

Builtins:

```tsx theme={null}
style.header({ margin: { bottom: 10 } }),
style.headline({ margin: { bottom: 4 } }),
style.legend.top({ margin: { bottom: 8 } }),
style.legend.bottom({ margin: { top: 16, bottom: 10 } }),
style.legend.left({ margin: { right: 10 } }),
style.legend.right({ margin: { left: 10 } }),
style.axisLabel.top({ margin: { bottom: 8 } }),
style.axisLabel.bottom({ margin: { top: 4, bottom: 16 } }),
style.tickLabel({ offset: 10 }),
style.tickLabel.left({ offset: 14 }),
style.tickLabel.right({ offset: 14 }),
style.footer({ margin: { top: 16 } }),
```

A tight preset that only wants less space below the title:

```tsx theme={null}
style.header({ margin: { bottom: 4 } });
style.tickLabel({ offset: 6 });
```

`style.header({ margin: 4 })` would also add 4px above the title, on top of the padding.

`legend.margin` does nothing when the legend track is empty. Direct labels sit on the plot and read `style.directLabel`.

## Panel overflow

The **panel** is the plot area. Data labels and difference arrows can reach past its edge, and
`panel.overflow` says what the engine does about it — per content type, per direction:

```tsx theme={null}
config({
  panel: {
    overflow: {
      dataLabels: { x: 'inside', y: 'outside' },
      differenceArrows: { x: 'outside', y: 'outside' },
    },
  },
});
```

<ParamField path="overflow.dataLabels" type="{ x: PanelOverflowStrategy; y: PanelOverflowStrategy }" default="{ x: 'inside', y: 'inside' }">
  Strategy for [data labels](/sdk-next/config/data-labels) that reach past the panel edge.
</ParamField>

<ParamField path="overflow.differenceArrows" type="{ x: PanelOverflowStrategy; y: PanelOverflowStrategy }" default="{ x: 'outside', y: 'outside' }">
  Strategy for difference-arrow annotations.
</ParamField>

Each direction takes one of three strategies:

* `'outside'` — the element lands outside the panel frame and the frame shrinks to make room.
* `'inside'` — the element stays inside the frame and the content within the frame shrinks instead.
* `'none'` — no accommodation; the element may overlap whatever is beside it.

Overflow accommodation applies to cartesian charts.

## Text scale

<ParamField path="style.graph.textScale" type="number" default="1">
  A multiplier applied to every text element in the chart. `1.2` makes titles, axis labels, tick
  labels and data labels 20% larger. Authored on `style.graph`.
</ParamField>

```tsx theme={null}
styles({ defaults: [style.graph({ textScale: 1.2 })] });
```

It changes measured text, and therefore the size of every region the engine arranges. `gap`,
`offset`, `margin`, padding and stroke widths do not scale.

<Note>
  Renderer contract: a [custom renderer](/sdk-next/extending/slots) must apply `textScale` at both
  text measurement and CSS render time. The engine assumes the measured sizes it receives already
  include the multiplier, so applying it to only one of the two throws the layout out. Slot
  `measure` callbacks receive it on `SlotMeasureContext`.
</Note>

## Related

* [Styling](/sdk-next/config/styling) — the graph background, frame ring, corner radius, `textScale`, outer `padding` and chrome `margin`
* [Legend](/sdk-next/config/legend) — legend position stays on `config.legend`


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.