Annotations help to add context and focus to a chart. They can be static, when the chart designer wants to highlight elements such as outliers or inflection points to tell a story. Or they can be interactive, with the user driving the exploration with the mouse. Annotations might be bound to the data (like interactive tips showing details on demand), or simply reflect the current mouse position in the coordinate system, giving the user a sense of orientation. We sometimes want to make annotations work across series (in particular for time series), or across facets (e.g. for easier cross-chart comparisons when data are split across small multiples).

In this post we explore five annotation patterns that can improve user understanding and engagement, and share code to implement each in Observable Plot.

Pointer-driven marks

“If you make a tooltip or rollover, assume no one will ever see it,” said Archie Tse, Graphics Director at The New York Times, in 2016. Making an interactive tip with a visible default state when the user is not interacting helps inject more editorial guidance into a visualization — while still allowing the engaged user to drive their own exploration of details.

Starting from a recent example published in the New York Times (a timeline tracking electoral polls), we implement a pointer-driven mark that defaults to a static annotation when the user is not interacting with the chart. As soon as they start hovering over the chart, the user seamlessly takes control of the annotation and can start exploring on their own.

Prior to user interaction, a static tip highlights only the most recent polling values. When a user hovers over the data, they take control of the annotation.

Learn about the logic in this step-by-step walkthrough on implementing pointer-driven marks in Plot.

Continuous crosshairs

Plot’s crosshair uses the pointer transform to snap to the data. In some cases, you’ll want the interaction to report instead on the current pointer position in the data space — to give a sense of orientation, or to understand where there is no data. A continuous crosshair thus focuses on the axes in the coordinate system. This also allows a chart to be an input for coordinates ⟨x, y⟩.

See how to implement continuous crosshairs in Plot, and check out how they’re useful when exploring the diamonds dataset.

Cross-facet crosshairs

Reacting to the pointer-driven marks notebook described above, Yuri Vishnevsky asked: “Can we highlight all ‘related points’ across all facets when hovering on a single point?”

The answer, as shown below and implemented in this notebook, is yes. With cross-facet crosshairs, the chart becomes an input for coordinates ⟨x, y, fx, fy⟩. (As an aside, this features an alternative implementation of the continuous crosshair.)

See the code to create cross-facet crosshairs in Plot.

Staggered axes

Sometimes you have a lot of tick labels to display on an axis — too many, in fact, to be readable due to overlap. A classic technique to avoid occlusion is to stagger axis text on alternating rows. But what if a two-row stagger still doesn’t solve your occlusion issues?

Here, we take text staggering to the extreme by offsetting labels across 10 rows (below, for a bioinformatics chart visualizing protein sequences) to keep a great number of tick labels separated and readable. For even more clarity, the axis text follows the pointer, highlighting the aligned tick label as a user hovers over the chart series.

See the code to create staggered axes in Plot.

Grouped tips

A very common pattern, for charts with multiple series, is to add an interactive tip that simultaneously displays the y values for all the series at a given x position (say, by date).

In this example, we use Plot’s render option — which lets you override or extend the default mark’s rendering method — to create a custom tip mark that shows the current value of all series in a stacked area chart.

See how we create grouped tips in Plot.

Build bespoke, interactive charts with Observable

Annotations add context and help viewers dive into the data for deeper insights and a more engaging user experience. The five examples above highlight unique and useful annotation patterns, implemented in Observable Plot. To start creating custom, interactive charts with Plot, here’s where to start: