---
url: https://chartbuddy.io/embed/docs/configuration/text-boxes.md
---
# Text boxes

Free callouts on the chart. In the editor they are **Add text box**; in `chartData` they live at top-level **`multilines`** (an array).

[Title, subtitle & footnote](/configuration/title-subtitle-footnote) are the same multiline text shape, but as **fixed docked furniture** — not members of `multilines`.

```js
multilines: [
  {
    id: 'multiline-callout-1',
    text: 'Note: figures are unaudited.',
    visible: true,
    leftXPercentage: 0.62,
    topYPercentage: 0.12,
    positionRelativeTo: 'drawableChartArea',
    width: 160,
    fontSize: 11,
    backgroundColor: 'transparent',
    movable: true,
    deletable: true,
  },
]
```

Defaults seed `multilines: []`. There is no `textBoxes` or `annotations.textBoxes` key on `chartData`.

***

## Free boxes vs docked furniture

| | Text boxes (`multilines[]`) | Title / subtitle / footnote |
|---|---|---|
| Storage | Array of N boxes | Three fixed keys: `title`, `subtitle`, `footnote` |
| Placement | Free — you set `%` coords | Docked — engine places them each draw |
| Plot space | Overlay only (does not reserve margin) | Reserves top / bottom margin |
| Movable / deletable | Usually `true` | `false` |
| `positionRelativeTo` | Usually `'drawableChartArea'` | `'fullChart'` |
| Docs | This page | [Title, subtitle & footnote](/configuration/title-subtitle-footnote) |

Axis titles under `axes.*.axisTitle` also use multiline text, but they are axis chrome — see [Titles & chrome](/axes/titles-and-chrome). Not free text boxes.

***

## Placement

| Field | Role |
|---|---|
| `leftXPercentage` / `topYPercentage` | Position as fractions of the reference area (roughly `0`–`1`) |
| `positionRelativeTo` | `'drawableChartArea'` — plot area (default for free boxes). `'fullChart'` — full canvas |
| `width` | Wrap width in px (editor ~130, a typical hand-authored width is `160`) |
| `movable` | `true` so the box can be dragged in edit mode |

Free boxes can overlap series and labels because they do not push the plot. Precise placement is easiest by dragging in edit mode, then exporting config.

***

## Fields

| Field | Type | Notes |
|---|---|---|
| `id` | string | Unique; editor uses `multiline-…` |
| `text` | string | Plain text or inline HTML (`<font>`, `<b>`, `<br>`, …) — same rules as title furniture |
| `visible` | boolean | Off unless `true` and `text` is non-empty |
| `fontSize` | number | Points (default `11`) |
| `backgroundColor` | string | e.g. `'transparent'` or a callout fill |
| `leftXPercentage` / `topYPercentage` | number | See placement |
| `positionRelativeTo` | string | `'drawableChartArea'` | `'fullChart'` |
| `width` | number | Wrap width (px) |
| `movable` / `deletable` | boolean | Defaults `true` for free boxes |
| `selectors.resizable` | boolean | Editor may set `true` for resize handles |

***

## Examples

Plain callout:

```js
multilines: [
  {
    id: 'note-1',
    text: 'Excludes one-offs.',
    visible: true,
    leftXPercentage: 0.7,
    topYPercentage: 0.15,
    positionRelativeTo: 'drawableChartArea',
    width: 140,
    fontSize: 10,
    backgroundColor: 'transparent',
    movable: true,
    deletable: true,
  },
]
```

Styled HTML + fill:

```js
multilines: [
  {
    id: 'highlight-1',
    text: '<font face="Arial" color="#111827"><b>Peak quarter</b></font>',
    visible: true,
    leftXPercentage: 0.55,
    topYPercentage: 0.2,
    positionRelativeTo: 'drawableChartArea',
    width: 160,
    fontSize: 11,
    backgroundColor: '#E8E8E8',
    movable: true,
    deletable: true,
  },
]
```

Replace or append the whole `multilines` array on `setChartData` / `update` when managing multiple boxes (arrays typically replace rather than deep-merge item-by-item).

***

## Tips

* Product name: text box. Data path: `multilines`.
* For chart title / units / source line, use [title, subtitle & footnote](/configuration/title-subtitle-footnote) so layout reserves space correctly.
* Prefer edit-mode placement + `getChartData()` / `exportConfig()` when coordinates matter.
