Annotations in Python
Annotations are chart children painted above data marks. Their anchors use data
coordinates, so they stay aligned while users pan and zoom. Text offsets such
as dx and dy are screen-space pixels, which keeps a label legible without
changing its data anchor.
When to Use
Use annotations to explain important coordinates without changing the underlying data marks. Rules and bands show references or ranges; labels, markers, arrows, and callouts draw attention to individual observations.
Live Demo
Rules and Bands
Threshold
threshold(value, axis=...) adds a semantic, optionally labeled reference
boundary on either axis.
Horizontal Line
hline(y) draws a horizontal rule at one y value.
Vertical Line
vline(x) draws a vertical rule at one x value.
Bands
x_band(x0, x1) and y_band(y0, y1) shade an interval on the corresponding
axis.
Threshold Zone
threshold_zone(start, end, axis=...) adds a semantic shaded interval on either
axis.
threshold is an annotation alias for a horizontal or vertical rule; it is
not a data mark. threshold_zone similarly selects an x or y band.
Labels, Markers, and Arrows
Callout
callout pins explanatory text to a point with configurable screen-space dx
and dy offsets.
Arrow
arrow(x0, y0, x1, y1) connects two coordinates and points toward the end.
Label
label attaches concise text to a coordinate with label-oriented positioning.
Text
text places free text at a coordinate. Use it when no marker or connector is
needed.
marker adds a point symbol and optional label. It uses the same data-coordinate
and screen-space offset model as the annotations above.
Data and Coordinates
Annotation coordinates use the chart's axis space. Rules and markers take scalar coordinates or categories, bands take two endpoints, and arrows take a start and end point. They do not require a separate data table.
Styling and Paint Order
Annotation geometry uses color, width, opacity, and component-specific
stroke or marker props. These are annotation controls, not the compiled mark
CSS subset.
Annotation labels are browser DOM elements. Their class_name and style
values can customize the label, and chart-level styling can target the stable
annotation_label slot. Geometry opacity is independent from label text;
use annotation-style label_opacity only when the label should also fade.
Keep geometry in the component props when output must agree across HTML, SVG,
and native PNG.
If more than one annotation occupies the same coordinate, declaration order controls their paint order. Exact signatures and defaults are in Marks and components reference.
API Reference
xy.vline
A vertical rule annotation at an x coordinate or x-axis category.
Props
| Prop | Type | Description |
|---|---|---|
x | CoordinateLike | X coordinate or category where the rule is drawn. |
text | Optional[str] | Optional label displayed beside the rule. |
color | Optional[str] | Rule color. |
width | float | Rule width in pixels. |
opacity | float | Rule opacity from zero to one. |
class_name | Optional[str] | DOM class name applied to the annotation. |
style | Optional[dict[str, StyleValue]] | Annotation style overrides. |
xy.hline
A horizontal rule annotation at a y coordinate or y-axis category.
Props
| Prop | Type | Description |
|---|---|---|
y | CoordinateLike | Y coordinate or category where the rule is drawn. |
text | Optional[str] | Optional label displayed beside the rule. |
color | Optional[str] | Rule color. |
width | float | Rule width in pixels. |
opacity | float | Rule opacity from zero to one. |
class_name | Optional[str] | DOM class name applied to the annotation. |
style | Optional[dict[str, StyleValue]] | Annotation style overrides. |
xy.x_band
A vertical span annotation between two x coordinates or categories.
Props
| Prop | Type | Description |
|---|---|---|
x0 | CoordinateLike | Starting x coordinate or category. |
x1 | CoordinateLike | Ending x coordinate or category. |
text | Optional[str] | Optional label displayed in the band. |
color | Optional[str] | Band color. |
opacity | float | Band opacity from zero to one. |
class_name | Optional[str] | DOM class name applied to the annotation. |
style | Optional[dict[str, StyleValue]] | Annotation style overrides. |
xy.y_band
A horizontal span annotation between two y coordinates or categories.
Props
| Prop | Type | Description |
|---|---|---|
y0 | CoordinateLike | Starting y coordinate or category. |
y1 | CoordinateLike | Ending y coordinate or category. |
text | Optional[str] | Optional label displayed in the band. |
color | Optional[str] | Band color. |
opacity | float | Band opacity from zero to one. |
class_name | Optional[str] | DOM class name applied to the annotation. |
style | Optional[dict[str, StyleValue]] | Annotation style overrides. |
xy.threshold
A semantic threshold rule on the x or y axis.
Props
| Prop | Type | Description |
|---|---|---|
value | CoordinateLike | Coordinate or category where the threshold is drawn. |
axis | str | Axis receiving the threshold, ``x`` or ``y``. |
text | Optional[str] | Optional threshold label. |
color | Optional[str] | Rule color. |
width | float | Rule width in pixels. |
opacity | float | Rule opacity from zero to one. |
class_name | Optional[str] | DOM class name applied to the annotation. |
style | Optional[dict[str, StyleValue]] | Annotation style overrides. |
xy.threshold_zone
A semantic threshold band on the x or y axis.
Props
| Prop | Type | Description |
|---|---|---|
start | CoordinateLike | Starting coordinate or category. |
end | CoordinateLike | Ending coordinate or category. |
axis | str | Axis receiving the band, ``x`` or ``y``. |
text | Optional[str] | Optional threshold label. |
color | Optional[str] | Band color. |
opacity | float | Band opacity from zero to one. |
class_name | Optional[str] | DOM class name applied to the annotation. |
style | Optional[dict[str, StyleValue]] | Annotation style overrides. |
xy.text
A text annotation anchored at an x/y coordinate or category.
Props
| Prop | Type | Description |
|---|---|---|
x | CoordinateLike | Anchor x coordinate or category. |
y | CoordinateLike | Anchor y coordinate or category. |
value | str | Text to display. |
dx | float | Horizontal pixel offset from the anchor. |
dy | float | Vertical pixel offset from the anchor. |
color | Optional[str] | Text color. |
anchor | str | Text alignment relative to the anchor point. |
class_name | Optional[str] | DOM class name applied to the annotation. |
style | Optional[dict[str, StyleValue]] | Annotation style overrides. |
xy.label
Create a positioned text label.
Props
| Prop | Type | Description |
|---|---|---|
x | CoordinateLike | Anchor x coordinate or category. |
y | CoordinateLike | Anchor y coordinate or category. |
value | str | Text to display. |
dx | float | Horizontal pixel offset from the anchor. |
dy | float | Vertical pixel offset from the anchor. |
color | Optional[str] | Text color. |
anchor | str | Text alignment relative to the anchor point. |
class_name | Optional[str] | DOM class name applied to the annotation. |
style | Optional[dict[str, StyleValue]] | Annotation style overrides. |
xy.marker
A point marker annotation with an optional label.
Props
| Prop | Type | Description |
|---|---|---|
x | CoordinateLike | Marker x coordinate or category. |
y | CoordinateLike | Marker y coordinate or category. |
text | Optional[str] | Optional marker label. |
color | Optional[str] | Marker fill color. |
size | float | Marker size in pixels. |
symbol | str | Marker symbol name. |
stroke_color | Optional[str] | Marker outline color. |
stroke_width | float | Marker outline width in pixels. |
opacity | float | Marker opacity from zero to one. |
dx | float | Horizontal label offset in pixels. |
dy | float | Vertical label offset in pixels. |
anchor | str | Label alignment relative to the marker. |
class_name | Optional[str] | DOM class name applied to the annotation. |
style | Optional[dict[str, StyleValue]] | Annotation style overrides. |
xy.arrow
An arrow annotation from one data coordinate to another.
Props
| Prop | Type | Description |
|---|---|---|
x0 | CoordinateLike | Starting x coordinate or category. |
y0 | CoordinateLike | Starting y coordinate or category. |
x1 | CoordinateLike | Ending x coordinate or category. |
y1 | CoordinateLike | Ending y coordinate or category. |
text | Optional[str] | Optional arrow label. |
color | Optional[str] | Arrow color. |
width | float | Arrow width in pixels. |
opacity | float | Arrow opacity from zero to one. |
class_name | Optional[str] | DOM class name applied to the annotation. |
style | Optional[dict[str, StyleValue]] | Annotation style overrides. |
xy.callout
A text callout offset from a data coordinate with a pointer arrow.
Props
| Prop | Type | Description |
|---|---|---|
x | CoordinateLike | Anchor x coordinate or category. |
y | CoordinateLike | Anchor y coordinate or category. |
value | str | Callout text. |
dx | float | Horizontal pixel offset from the anchor. |
dy | float | Vertical pixel offset from the anchor. |
color | Optional[str] | Callout color. |
width | float | Pointer width in pixels. |
opacity | float | Callout opacity from zero to one. |
anchor | str | Text alignment relative to the callout point. |
class_name | Optional[str] | DOM class name applied to the annotation. |
style | Optional[dict[str, StyleValue]] | Annotation style overrides. |
FAQ
How do I add a horizontal line to a chart in Python?
Add xy.hline(y) as a chart child, e.g.
xy.hline(55, text="SLO", color="#2563eb", width=2); xy.vline(x) is the
vertical equivalent. For a reference boundary with semantic intent on either
axis, use xy.threshold(value, axis="y", text="target") instead.
How do I shade a region or band on a chart?
Use xy.x_band(x0, x1) or xy.y_band(y0, y1) to shade an interval on the
corresponding axis, with text, color, and opacity to label and style it.
xy.threshold_zone(start, end, axis=...) does the same for a semantic
"acceptable range" style zone on either axis.
How do I label a data point and draw an arrow to it on a chart?
xy.callout(x, y, "note", dx=-60, dy=-30) pins explanatory text to a point
with a connector, while xy.arrow(x0, y0, x1, y1, text=...) draws a
free-standing arrow between two coordinates. For text alone use
xy.label(x, y, "peak", dy=-16) or xy.text(x, y, "note"), and
xy.marker(x, y, text=...) adds a point symbol with an optional label.
Why do my annotations stay aligned when I pan or zoom the chart?
Annotation anchors use data coordinates, so rules, bands, markers, and callouts
track the data as the viewport changes. Only the text offsets dx and dy are
screen-space pixels, which keeps labels legible without moving their data
anchor.