Reference lines, shapes and annotations

Plotly · Practical · 10 min

Annotations direct attention to what matters, such as a target, an incident window or an outlier.

Plotly has convenience methods for the most common highlights:

  • fig.add_hline(y=100, line_dash="dash", annotation_text="target") and fig.add_vline(x=...) draw lines across the whole plot.
  • fig.add_hrect(y0=..., y1=...) and fig.add_vrect(x0="2026-03-01", x1="2026-03-08", fillcolor="red", opacity=0.15, line_width=0) shade bands, ideal for incidents or weekends.
  • fig.add_annotation(x=..., y=..., text="peak", showarrow=True, arrowhead=2, ax=0, ay=-40) labels a point; ax/ay are the arrow tail offset in pixels.

On faceted or subplot figures these accept row= and col= (or "all") to target panels.

Under the hood they add entries to fig.layout.shapes and fig.layout.annotations. Positions are interpreted through xref and yref: "x"/"y" mean data coordinates, "paper" means fractions of the plotting area (0 to 1), and "x domain" means fractions of one axis's domain. add_hline uses xref="x domain" so the line always spans the full width regardless of zoom.

add_shape(type="rect" | "line" | "circle" | "path", ...) draws arbitrary shapes, and layer="below" puts them behind the data. fig.add_layout_image places logos.

Annotations also work as free text, for example a source note at xref="paper", yref="paper", x=0, y=-0.15.

Example

import plotly.express as px

df = px.data.stocks()
fig = px.line(df, x="date", y="AAPL")

fig.add_hline(y=1.0, line_dash="dash", line_color="gray",
              annotation_text="start value", annotation_position="bottom right")
fig.add_vrect(x0="2018-10-01", x1="2018-12-31", fillcolor="red",
              opacity=0.12, line_width=0, annotation_text="Q4 selloff")
peak = df.loc[df["AAPL"].idxmax()]
fig.add_annotation(x=peak["date"], y=peak["AAPL"], text="peak",
                   showarrow=True, arrowhead=2, ax=0, ay=-40)
fig.add_annotation(text="Source: px.data.stocks", xref="paper", yref="paper",
                   x=0, y=-0.15, showarrow=False)

print(len(fig.layout.shapes), len(fig.layout.annotations))  # 2 4
print(fig.layout.shapes[0].xref)                           # x domain
fig.write_html("annotated.html")

Remember

  • add_hline/add_vline/add_hrect/add_vrect cover most highlights
  • add_annotation labels points; ax/ay offset the arrow in pixels
  • xref/yref choose data, paper or axis-domain coordinates

Watch out for

  • Positioning a note with data coordinates when it should stay fixed relative to the plot area (use xref='paper').

Check yourself

  1. You want a caption below the plot area that does not move when the user zooms. Which reference do you use?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: plotly.com/python/shapes/