Skip to content

Annotations

Annotations guide the reader to the story in the data. They explain design elements, highlight significant values, and provide context the chart alone cannot convey. Used well, they do most of the storytelling.

Purpose

Annotations guide the reader to the story in the data. They explain design elements, highlight significant values, and provide context that the chart alone cannot convey.

A chart without annotations presents data. A chart with annotations tells a story.

Types of annotations

TypeDescriptionUse for
Reference line (horizontal)Line at a specific y-valueAverages, targets, benchmarks, thresholds
Reference line (vertical)Line at a specific x-valueEvents in time, policy changes, milestones
Range band (horizontal)Shaded region between two y-valuesAcceptable zones, confidence intervals
Range band (vertical)Shaded region between two x-valuesTime periods (recessions, campaigns)
Point annotationMarker + label at a specific data pointOutliers, peaks, significant individual values
CalloutLabel with connector lineExplanations positioned away from crowded areas

Best practices

  • Maximum 3-4 annotations per chart to avoid overwhelming readers
  • Position explanatory text as close to the relevant data as possible
  • Use two text hierarchy levels within annotations (e.g., bold primary, regular secondary) — not more
  • Use text outlines when annotations overlay grid lines
  • On mobile, hide less important annotations or move them below the chart
  • Write annotations that add context beyond what the data shows ("why" not just "what")

Annotations as storytelling

TIP

"If everything is emphasized, nothing is." Prioritize ruthlessly. The annotation should match the chart's headline — reinforce the main point, don't dilute it with tangential observations.

A good annotation reads like a caption to a photograph: it tells the reader what matters here and why. Avoid restating what the axis already shows.

Example

Bad: "March: 2,300 units" (redundant with the data label)

Good: "New packaging launched March 3 — unit sales jumped 40%"

How Blueprint Chart applies annotations

Blueprint Chart implements annotations as first-class citizens: Point, Range, and Free annotations are part of the DSL grammar and the rendering pipeline. Annotations are ordered and rendered above the chart geometry but below tooltips, so they sit visually in the foreground without interfering with hover interaction.

bpc
chart line {
  title = "Unit sales jumped after new packaging launched"

  data {
    "Jan" = 1600
    "Feb" = 1700
    "Mar" = 2300
    "Apr" = 2350
    "May" = 2420
  }

  annotation point {
    at    = "Mar"
    label = "New packaging launched March 3"
  }
}

See the BPC DSL Specification for the full annotation grammar.

Worked example: a point annotation tied to a peak

bpc
chart line {
  title = "Bitcoin surged past $90,000 in 2024"
  description = "USD, year-end closing price"
  source = "CoinGecko"
  colors = "#f7931a"

  data {
    "2020" = 28949
    "2021" = 46306
    "2022" = 16547
    "2024" = 93429
  }

  annotation "2021" {
    text = "All-time high cycle"
    dy = -12
    showArrow = true
  }
}

From packages/lib/src/samples/bitcoin-price.bpc

The annotation is keyed by the same x-value the data uses ("2021"), placed -12 pixels above the point and connected with showArrow. One annotation, one observation — the chart stays under the 3–4 annotation ceiling and the label sits in the negative space above the data, not on top of the line.

Worked example: a callout with curved leader line

bpc
chart bar-vertical {
  title = "China emits more CO₂ than the US and India combined"
  description = "Annual emissions in billion tonnes, 2023"
  colors = "#abb8c3"
  valueLabels = true

  data {
    "China" = 11.9
    "United States" = 4.78
    "India" = 2.88
    "Russia" = 1.78
  }

  colorize "China" {
    color = "#e15759"
  }

  annotation "India" {
    text = "Surpassed EU in 2023"
    showLine = true
    anchorDirection = N
    textOffsetX = 66
    textOffsetY = -41
    lineStyle = curve-left
    showArrow = true
  }
}

From packages/lib/src/samples/co2-emissions.bpc

A callout adds the why alongside the data ("Surpassed EU in 2023") — a sentence that the bar height alone cannot communicate. lineStyle = curve-left plus the text offsets keep the label well clear of the bars; anchorDirection = N attaches the leader line to the top of the "India" bar.

See also

Released under the MIT License. Built static-first — your data never leaves the page.