Published-release documentation · release compatibility

Legends

Grouped density area chart of car acceleration
Derived density paths with grouped color and guides.

At a glance

Action Shortest call Inference/defaults Result
createLegend createLegend() Current/unique compatible mark; right position Categorical, size, stroke-width, gradient, interval, or opacity guide; sampled channels and gradient ticks accept exact values
editLegend editLegend({ position: "left" }) Unique existing legend; omitted properties retained Rematerialized content, layout, and appearance
editLegendBlock editLegendBlock({ target: "points", channel: "size", title: "Magnitude" }) Explicit mark and represented channel Only the selected logical block is rematerialized
Focused edits editLegendLabels({ fontSize: 11 }) Same target inference as editLegend One legend component rematerialized
removeLegend removeLegend({ channels: ["size"] }) Existing legend owner; omitted channels remove all Selected complete blocks removed

Legends are inferred from final mark encodings and materialized as concrete graphics. Start with the family that matches the encoded channel and use the editing page when changing an existing guide.

Right and left legends start at the top of the actual plot, excluding the chart title. The complete legend includes its visible title, symbols, labels, and optional border. Multiple blocks share one stack whose top aligns with the plot; blocks retain their spacing. Shared facet legends align with the top of the translated child plots. When offset is omitted, the native gap follows the actual occupied axis guides on the same edge, including left and right. An explicit offset remains anchored to the plot.

Polar theta and radial labels and titles also reserve space outside the plot. Their measured bounds update the default legend clearance after font edits, Canvas resizing, and snapshot restoration. Top, bottom, and in-plot corner positions keep their own alignment rules.

Editing one block

Use the optional singular channel on editLegend or a focused editor to select one existing block:

Contextual fragment. Use an ES module with the imports, data, and prepared resource state described in this section. Caller-provided receivers: program. Resolve these names from setup in this fragment or section; alternatives branch from the same base.

// Fragment: program already owns color and opacity legends for one point mark.
program.editLegendLabels({ channel: "opacity", fontSize: 10 });

This changes only the selected block. It preserves sibling typography and sample values. Specify target when more than one mark owns legends. Singular channel cannot accompany plural channels, which replaces whole-target content, or whole-group blockLayout/at controls.

Supported legend families

Legend family Supported marks Channels
Categorical color/shape/dash point, line, area, bar, rect, arc, text ordinal color; point shape; line strokeDash; compatible composites follow family constraints
Categorical stroke point, line, area, bar, rect, arc, rule, tick ordinal stroke; final-item or series identities
Continuous color gradient point, aggregate bar, rect, text, tick sequential color; gradient swatch, no symbol recipe
Continuous stroke gradient point, line, area, bar, rect, arc, rule, tick sequential stroke; separate gradient, no symbol recipe
Discretized color interval point, aggregate bar, rect, tick quantize/quantile/threshold color; rectangle swatches
Discretized stroke interval point, line, area, bar, rect, arc, rule, tick quantize/quantile/threshold stroke; outline-colored interval symbols
Size point size; continuous numeric samples or every discrete interval; point glyph symbol
Opacity point, line, bar quantitative opacity samples; representative point symbol even for line consumers; Rule opacity has no legend
Stroke width line, rule quantitative strokeWidth samples; line symbol

Focused legend families

Categorical legendsCreate categorical, size, and interval guides and control their layout. Continuous legendsGradient color and sampled opacity guides. Composite symbolsLayered line, point, and swatch recipes plus optional borders. Edit and removeAtomic component edits, rematerialization, trace, and removal.

Errors and limitations

Continuous color legends support point, aggregate-bar, and rect marks. Continuous stroke legends support every stroke-capable mark at its documented item/series grain. Field Opacity legends support Point and Line; discretized color legends support Point, aggregate Bar, and Rect. Interactive legends are unsupported. Combined point-series and size legends support every edge. Continuous size blocks sample the domain; discrete size blocks show every interval. Side positions stack the blocks; horizontal positions place them in rows. A left block must fit outside any left y-axis guides; omitted offsets reserve this clearance automatically. Stroke-width legends support all four edges and plot corners through createLegend and editLegendLayout. Use layout: "edge", offset, itemGap, and horizontal align, direction, columns, and titlePosition controls. Title, count, label/title styles, and border are editable. Side positions require vertical direction, center alignment, one column, and a top title. Symbol recipes, gradient, and order are unsupported; edit quantitative mapping through editScale. Continuous size, opacity, stroke-width, color-symbol and color/stroke-gradient legends accept values for exact ascending samples. Exact values must fit the effective domain and cannot be combined with count; use editLegend({ values: "auto" }) to return to the remembered automatic sample count. Automatic samples retain exact domain endpoints, so rounding cannot extrapolate opacity beyond its range. For a gradient tick selection, use editLegend({ channel: "color", values: [40, 60, 80] }) on an existing matching scale. Use editLegendBlock() for sampled blocks, order, title, labels, spacing, and supported symbol appearance when a target has multiple blocks. Right-side layout requires sufficient right margin; bottom layout requires sufficient bottom margin; top layout requires enough top margin for its title, item grid, offset, and optional border. A fixed outer Canvas reports a layout error when there is insufficient space. Use createCanvas({ plot: { width, height } }) to retain exact plot dimensions while measured guide overflow grows the outer margins. Symbol layers are never dropped.

Space rows by content

Create the complete legend first, then refine its spacing. This fragment requires an existing item-based legend:

Contextual fragment. Use an ES module with the imports, data, and prepared resource state described in this section. Caller-provided receivers: program. Resolve these names from setup in this fragment or section; alternatives branch from the same base.

program.editLegendLayout({ rowPadding: 7, titlePadding: 20 });
Three blue size samples have equal seven-pixel gaps and clear a separate title by twenty pixels
Painted sample heights of 18, 26 and 42 pixels have equal 7-pixel gaps; the title clears the body by 20 pixels.

rowPadding is the empty vertical distance between adjacent rows’ occupied sample and label bounds. It accounts for each row’s own symbol size and stroke; a text-only overflow row reserves only its label. Multi-column grids measure the union of each row. itemGap continues to control horizontal spacing and supplies the original vertical pitch when rowPadding is omitted.

titlePadding independently sets the occupied title-to-body distance: vertical for top or bottom titles, horizontal for an inline left title. Hidden titles reserve no distance. Text bounds use the library’s deterministic font-size and hard-line-break measurement, rather than browser-specific glyph ink.

Both values accept finite non-negative logical pixels, including zero. editLegend and editLegendLayout accept "auto" to remove either policy; omitting a value preserves it. Creation accepts numbers only. The original layout is unchanged when neither policy is supplied. Gradient strips accept titlePadding only; reset rowPadding before switching an item legend to a gradient. Both options require layout: "edge", rather than "legacy-bottom". See editing legends for block selection.

Put a compact categorical legend inside the plot

Use a corner position such as "top-left" and overflow: { maxItems: 29 } in createLegend or editLegend. The first 29 categories keep their original symbols; a text-only summary reports the remaining count. border: { background: "white" } provides an opaque panel behind the legend. The limit changes the displayed guide only, preserving every data row and color assignment. See the exact legend contract for supported anchors and layout restrictions.

Title alignment.

Use titleStyle: {align: "left"} to align a top title inside the measured legend content block. The same style accepts "center" and "right" for categorical, gradient, interval, size, opacity and stroke-width legends. This text alignment is separate from the complete legend’s placement align. Omitting it preserves the native layout’s current default.

On an existing legend, editLegendTitle({align: "right"}) changes only that choice. editLegendTitle({align: "auto"}) restores the native default; the whole edit equivalent is editLegend({titleStyle: {align: "auto"}}). These are fragments requiring an existing legend. A top-to-inline title transition can reset the choice in the same whole edit; inline titlePosition: "left" rejects an explicit title alignment. Border padding, group anchors, item positions and spacing retain their existing rules.

Guides · Series encodings · Canvas · Troubleshooting

When creating a separate size legend, an explicit position is honored even if a color or shape legend for the same mark uses another edge. Omit size position to inherit the categorical legend edge. Resizing retains that choice.

Documentation provenance

293 actions · sha256:e755591a2e5f5e2b494867583876e28020a478c5220b77bdc6ad469a6224891d