Chart annotation
Annotation is where a chart stops being a picture of data and becomes a statement someone can act on.
It is also the cheapest quality improvement available — mostly words, no code.
The title states the finding, not the subject
The highest-leverage rule in this pack.
| Subject title (weak) |
Takeaway title (strong) |
| ARR Bridge |
Churn offset half of new ARR this quarter |
| Monthly Revenue |
Revenue growth has flattened since March |
| Cohort Retention |
Cohorts since January retain 6 points better at month 3 |
| Budget vs Actual |
Three departments account for 80% of the overspend |
| Cash Forecast |
Runway reaches 11 months under the plan hiring pace |
The subject can be a smaller subtitle underneath. But the headline is what the reader takes away, so
it should be what you want them to take away.
Two disciplines follow from this:
- If you cannot write the takeaway title, you do not yet know what the chart is for. That is a
signal to stop and reconsider the chart, not to fall back on a subject title.
- The title must be defensible. It is a claim. If the data does not support it, change the
title — never overstate to make a slide land.
For an exploratory tool where the reader draws their own conclusion, a subject title is correct. Know
which one you are building.
Direct labels beat legends
A legend forces a lookup: read the colour, find the swatch, map back. Direct labels remove it.
- Line charts: label at the right end of each line, in the line's colour. No legend at all.
- Bar charts: value labels on or beside the bars.
- Stacked: label inside bands where they are wide enough; a legend only for the thin ones.
- Scatter: label the notable points, not all of them.
Keep a legend when there are many series, when the same legend serves several charts, or when marks
are too small to label. Then: order legend entries to match the visual order of the series —
alphabetical order forces the lookup you were trying to remove.
Use chartkit.avoidOverlap to separate crowded end-of-line labels while preserving their order.
Reference lines and bands
Context turns a number into a judgement.
| Reference |
Use |
| Target / plan |
Solid, muted, labelled with its value and version |
| Prior period |
Dashed, lighter |
| Benchmark band |
Shaded region with the range labelled |
| Threshold |
A rule where crossing means something — zero cash, a covenant |
| Average / median |
Only if the reader needs it; often clutter |
Rules:
- Label the line on the line, at its end. An unlabelled rule is a mystery.
- Muted, behind the data. A reference line competing with the series inverts the hierarchy.
- Name the version: "Plan (board approved Jan-26)". Plans get revised, and an unlabelled plan is
unreconcilable three months later.
- Benchmarks carry source, vintage, and stage: "SaaS median NRR 101% (2026, mid-market)". A
mid-market benchmark against an early-stage company misleads even when the number is right.
Callouts
Point at the two or three things that matter. More than that and none of them are emphasized.
Good callouts:
- The peak or trough, with its value and date
- The point where a trend changed, with the reason
- The current value, when the chart is mostly historical
- An outlier, with its explanation
A callout that just repeats the value is not a callout. $210K on a bar already labelled $210K
adds nothing. $210K — lowest since Jan, two enterprise deals slipped is a callout.
Keep them short, connect them to their mark with a thin leader line, and never let them obscure data.
Event annotation
Vertical rules for discrete events; shaded regions for periods.
- Short labels, rotated only if unavoidable.
- Muted styling — events are context, not data.
- A definition change gets an annotation and a visible break in the series. A smooth line across a
definition change is a false continuity claim, and it is the most damaging unannotated event
because it is invisible.
Axis labelling
- Units once, in the axis title or the tick format — never repeated on every tick and also in the
title.
- Pin the unit for the whole axis. Mixing
$1.2M and $900K makes the reader do unit
arithmetic; choose M and accept $0.9M.
- Say when an axis is truncated or log, in the axis label. A truncated axis that is not labelled
as such is a misrepresentation.
- Drop an axis title entirely when the tick format makes it obvious —
$4.8M needs no "Revenue
(USD millions)" above it.
- Fewer ticks than you think. Five or six is usually right; the gridlines carry the rest.
Provenance — what makes a figure checkable
Every data chart carries a footer:
Data as of 2026-08-19 14:20 ET · Period Jul 2026 (closed)
Source: finance.gl_summary · Subscription revenue agrees to GL 4100, variance $0.00
- Timezone always. "14:20" is not a time.
- Period status — open periods can still move, and the reader must know.
- Say if it has been proven, and give the variance. That one line changes how the number is
received.
- Small and muted (
--text-xs, --ink-muted). Present, not prominent.
Footnotes
For things that qualify the reading:
- Scope exclusions — "excludes intercompany"
- Restatements — "Q1 restated for the revenue reclass"
- Suppression — "cells with fewer than 5 customers suppressed"
- Estimates — "August is a forecast"
- Definition — a link to the metric definition, or the definition inline
Anything that would change a reader's interpretation goes near the number, not in a footnote.
Footnotes are for detail; qualifications that matter belong in the chart.
Checklist
Related skills
chart-selection — writing the takeaway before building
microcopy-and-states — the wider wording discipline
data-typography — how the labels are set
ui-antipatterns — unlabelled truncation and false precision
bridge-charts, timeseries-finance, cohort-charts — form-specific annotation
1---2name: chart-annotation3description: Titles, labels, reference lines, callouts, legends, and provenance on a chart - writing the takeaway rather than the subject, direct labelling instead of legends, benchmark bands with their stage and vintage, and the footnote discipline that makes a figure checkable. Trigger on "chart title", "caption", "legend", "annotate", "label the chart", "reference line", "benchmark line", "footnote", "what should the title say", "callout".4---56# Chart annotation78Annotation is where a chart stops being a picture of data and becomes a statement someone can act on.9It is also the cheapest quality improvement available — mostly words, no code.1011---1213## The title states the finding, not the subject1415The highest-leverage rule in this pack.1617| Subject title (weak) | Takeaway title (strong) |18|---|---|19| ARR Bridge | Churn offset half of new ARR this quarter |20| Monthly Revenue | Revenue growth has flattened since March |21| Cohort Retention | Cohorts since January retain 6 points better at month 3 |22| Budget vs Actual | Three departments account for 80% of the overspend |23| Cash Forecast | Runway reaches 11 months under the plan hiring pace |2425The subject can be a smaller subtitle underneath. But the headline is what the reader takes away, so26it should be **what you want them to take away**.2728Two disciplines follow from this:29301. **If you cannot write the takeaway title, you do not yet know what the chart is for.** That is a31 signal to stop and reconsider the chart, not to fall back on a subject title.322. **The title must be defensible.** It is a claim. If the data does not support it, change the33 title — never overstate to make a slide land.3435For an exploratory tool where the reader draws their own conclusion, a subject title is correct. Know36which one you are building.3738---3940## Direct labels beat legends4142A legend forces a lookup: read the colour, find the swatch, map back. Direct labels remove it.4344- **Line charts**: label at the right end of each line, in the line's colour. No legend at all.45- **Bar charts**: value labels on or beside the bars.46- **Stacked**: label inside bands where they are wide enough; a legend only for the thin ones.47- **Scatter**: label the notable points, not all of them.4849Keep a legend when there are many series, when the same legend serves several charts, or when marks50are too small to label. Then: order legend entries **to match the visual order** of the series —51alphabetical order forces the lookup you were trying to remove.5253Use `chartkit.avoidOverlap` to separate crowded end-of-line labels while preserving their order.5455---5657## Reference lines and bands5859Context turns a number into a judgement.6061| Reference | Use |62|---|---|63| **Target / plan** | Solid, muted, labelled with its value and version |64| **Prior period** | Dashed, lighter |65| **Benchmark band** | Shaded region with the range labelled |66| **Threshold** | A rule where crossing means something — zero cash, a covenant |67| **Average / median** | Only if the reader needs it; often clutter |6869Rules:70- **Label the line on the line**, at its end. An unlabelled rule is a mystery.71- **Muted, behind the data.** A reference line competing with the series inverts the hierarchy.72- **Name the version**: "Plan (board approved Jan-26)". Plans get revised, and an unlabelled plan is73 unreconcilable three months later.74- **Benchmarks carry source, vintage, and stage**: "SaaS median NRR 101% (2026, mid-market)". A75 mid-market benchmark against an early-stage company misleads even when the number is right.7677---7879## Callouts8081Point at the two or three things that matter. More than that and none of them are emphasized.8283Good callouts:84- The peak or trough, with its value and date85- The point where a trend changed, with the reason86- The current value, when the chart is mostly historical87- An outlier, with its explanation8889**A callout that just repeats the value is not a callout.** `$210K` on a bar already labelled `$210K`90adds nothing. `$210K — lowest since Jan, two enterprise deals slipped` is a callout.9192Keep them short, connect them to their mark with a thin leader line, and never let them obscure data.9394---9596## Event annotation9798Vertical rules for discrete events; shaded regions for periods.99100- Short labels, rotated only if unavoidable.101- Muted styling — events are context, not data.102- **A definition change gets an annotation and a visible break in the series.** A smooth line across a103 definition change is a false continuity claim, and it is the most damaging unannotated event104 because it is invisible.105106---107108## Axis labelling109110- **Units once, in the axis title or the tick format** — never repeated on every tick and also in the111 title.112- **Pin the unit for the whole axis.** Mixing `$1.2M` and `$900K` makes the reader do unit113 arithmetic; choose `M` and accept `$0.9M`.114- **Say when an axis is truncated or log**, in the axis label. A truncated axis that is not labelled115 as such is a misrepresentation.116- Drop an axis title entirely when the tick format makes it obvious — `$4.8M` needs no "Revenue117 (USD millions)" above it.118- Fewer ticks than you think. Five or six is usually right; the gridlines carry the rest.119120---121122## Provenance — what makes a figure checkable123124Every data chart carries a footer:125126```127Data as of 2026-08-19 14:20 ET · Period Jul 2026 (closed)128Source: finance.gl_summary · Subscription revenue agrees to GL 4100, variance $0.00129```130131- **Timezone always.** "14:20" is not a time.132- **Period status** — open periods can still move, and the reader must know.133- **Say if it has been proven**, and give the variance. That one line changes how the number is134 received.135- Small and muted (`--text-xs`, `--ink-muted`). Present, not prominent.136137---138139## Footnotes140141For things that qualify the reading:142143- Scope exclusions — "excludes intercompany"144- Restatements — "Q1 restated for the revenue reclass"145- Suppression — "cells with fewer than 5 customers suppressed"146- Estimates — "August is a forecast"147- Definition — a link to the metric definition, or the definition inline148149**Anything that would change a reader's interpretation goes near the number, not in a footnote.**150Footnotes are for detail; qualifications that matter belong in the chart.151152---153154## Checklist155156- [ ] Title states a finding you can defend157- [ ] Every series labelled directly, or a legend ordered to match the visual158- [ ] Units stated once, pinned per axis159- [ ] Truncated or log axes labelled as such160- [ ] Reference lines labelled with value and version161- [ ] Benchmarks carry source, vintage, and stage162- [ ] Two or three callouts, none merely repeating a value163- [ ] Definition changes annotated with a visible break164- [ ] Provenance footer with as-of, timezone, period status, source165- [ ] Nothing on the chart is decorative166167---168169## Related skills170171- `chart-selection` — writing the takeaway before building172- `microcopy-and-states` — the wider wording discipline173- `data-typography` — how the labels are set174- `ui-antipatterns` — unlabelled truncation and false precision175- `bridge-charts`, `timeseries-finance`, `cohort-charts` — form-specific annotation