Skip to main content
A combo chart layers two geoms with different y-scales — typically bars for one metric and a line for another on a second axis. It’s how you show two series whose units or magnitudes don’t share a scale.

Dual-axis example

Give each geom its own y through a layer-local mapping, and bind the line to the secondary axis with yScaleType: 'secondary'. Each layer also needs something to map to color, otherwise both resolve the same built-in mark color and neither earns a legend entry. A per-layer transform.constant synthesizes a categorical column holding that layer’s series name, and mapping it to color gives the layer its own palette color and its own legend item:
Each scale trains only on the layers bound to it, so the two metrics keep independent ranges. transforms on a layer run on top of any spec-level transforms and apply to that layer alone — reach for it whenever one geom needs a different shape of the data than its siblings. scale.ySecondary() is optional: the compiler infers one as soon as a layer declares yScaleType: 'secondary'. Declare it when you want to control the domain, the same as any other scale.

Configuring the second axis

The secondary axis is keyed ySecondary under axes, and it’s a sparse override — every field you leave out is inherited. position lands on the side opposite y; isVisible, grid and ticks come from y itself:

Styling one layer

Give a layer an id and a stylesheet entry can scope to it with { layer }. This is what makes an overlay line read as an overlay rather than another series:
overrides rather than defaults, because color here is decided by a mapping and only an override outranks one. See Styling for the full cascade.

When to share the axis instead

A second axis is right when the two layers measure different things. When they measure the same thing — an average, a target, a running total drawn over the bars it summarises — omit yScaleType and let the line sit on the primary scale. A dual axis there silently decouples the line from the bars it annotates:
For a flat reference line at a constant value, geom.rule() is the purpose-built layer — non-interactive by default, with an optional inline label, and painted through style.geom.rule({ color, strokeWidth, lineType }):