Dual Axes Charts

Sometimes you need to plot two things on the same timeline that simply do not belong to the same scale. Revenue and headcount. Inflation and GDP. Price and spread. If you force them onto one axis, one series becomes unreadable, and the chart turns into a polite lie.

A dual-axis chart solves this by keeping a shared X axis (time) while providing two independent Y axes, so each metric is shown in its natural units. The goal is not to pretend the metrics are comparable. The goal is to compare when they move and how their dynamics relate.

In RareCharts, DualAxes is exactly that: a time-based chart with two vertical scales.

To illustrate a real-world use case, this example uses a finance-native story: a convergence (arbitrage) strategy based on the idea that two similar instruments that temporarily diverged in price will later converge again.

One concrete version of this story exists in government bonds, where a newly issued “on-the-run” Treasury can trade slightly richer than the previous “off-the-run” issue for a period of time. Traders may position for convergence by going long the cheaper issue and hedging the richer one, expecting the price gap to compress as the market normalizes.

In the chart, the right axis (Y1) shows the price index of the two instruments over time. The left axis (Y2) shows the spread between them. Prices and spread are different categories, so they get different axes. The chart stays readable, and the relationship stays visible.

Axis behavior and formatting

Both axes are configured independently. You can set titles (y1Title, y2Title), control tick formatting (y1TickFormat, y2TickFormat), and, when needed, override the visible ranges (y1Domain, y2Domain) to keep the chart stable and comparable across screenshots, reports, or multiple panels.

In this example, the spread axis uses a signed format and treats very small values as clean zero, so you do not get the infamous +0.00 noise that makes charts look broken even when the data is fine.

Interaction

Dual Axes supports cursor inspection through a crosshair and a tooltip. The tooltip is fully customizable through tooltipFormat ({ date, points }), so you can present values in your product’s language instead of whatever generic tooltip someone thought was “good enough”.

Dual-axis charts are often implemented as a hack: two scales, mismatched formatting, confusing labels, and tooltips that quietly mix units. This component exists to make the dual-axis case predictable, explicit, and safe for real reporting: independent scales, consistent structure, and controlled formatting.

Dual Axes chart options

Common options shared by all chart types (title, subtitle, legend, legendPosition, source, theme) are documented on the Settings page.

Option Type Default Description
Layout
height number 280 Chart height in px.
margin object Inner padding {top, right, bottom, left}.
Right defaults to 92, left to 64 to give both axes room.
xPad number 8 Extra horizontal padding on both ends of the X scale.
Right axis — Y1

Y1 is drawn on the right side.

y1Domain [min, max] auto Override the Y1 scale domain.
Useful for keeping charts comparable across snapshots.
y1Ticks number 4 Tick count on Y1.
y1TickFormat function ,.2f (value) => string — Y1 tick labels.
y1LabelsOnly boolean true Show only tick labels; suppress the axis line.
y1Title string Axis title, rendered along the right edge.
Left axis — Y2

Y2 is drawn on the left side. Grid lines and the zero baseline are keyed to Y2.

y2Domain [min, max] auto Override the Y2 scale domain.
y2Ticks number 4 Tick count on Y2.
y2TickFormat function +.2f (value) => string — Y2 tick labels.
y2LabelsOnly boolean true Show only tick labels; suppress the axis line.
y2Title string Axis title, rendered along the left edge.
X axis
xTickFormat function '%m/%d' (date) => string — X tick labels.
Lines
curve string 'linear' D3 curve type for line series: 'linear', 'monotone', 'step', etc.
curveTension number 0 Tension for the 'cardinal' curve, 01.
strokeDash string SVG stroke-dasharray applied to all line series globally.
area boolean false Fill area under line series.
areaOpacity number 0.12 Area fill opacity.
areaBaseline 'zero' | 'min' | number 'zero' Area baseline anchor.
Bars
barOpacity number 0.35 Bar fill opacity.
barWidthRatio number 0.65 Bar width as a fraction of the time step width.
barGrouping 'overlap' | 'cluster' 'overlap' How multiple bar series are arranged. 'cluster' places them side by side.
Visibility
showGrid boolean true Show horizontal grid lines.
showXAxis boolean true Show the X (date) axis at the bottom.
showY1Axis boolean true Show the Y1 axis on the right.
showY2Axis boolean true Show the Y2 axis on the left.
End labels and markers
endLabels boolean true Show last-value labels at the right edge for line series.
endLabelsAxis 'y1' | 'y2' 'y1' Which axis to use when formatting end labels.
markers boolean false Point markers at each data sample on line series.
markerShape string 'circle' Marker shape: 'circle', 'square', 'diamond'.
markerSize number 4 Marker radius in px.
Interaction
crosshair boolean true Vertical tracker with dots at data points and a tooltip on hover.
tooltipFormat function ({ date, points }) => html — where points is [{name, value, color, fmt}].
Animation
animate boolean true Animate on first render.
duration number 650 Animation duration in ms.
ease string 'cubicOut' Easing: 'cubicOut', 'cubicInOut', 'linear'.
Per-series fields

Each object in the series array passed to setData():

name string 'Series N' Series name — used in legend and tooltip.
axis 'y1' | 'y2' 'y1' Which Y axis to plot against.
type 'line' | 'bar' 'line' Rendering type for this series.
color CSS color theme palette Series color.
strokeWidth number 2 Line thickness in px (lines only).
strokeDash string SVG dash pattern for this series only.
curve string global curve Curve override for this series.
area boolean global area Fill area under this series.
areaOpacity number global areaOpacity Per-series area opacity.
areaBaseline string | number global areaBaseline Per-series area baseline.
values array [{date, value}, ...] — the data points.