Legends in Python
Marks with a name= participate in the chart legend. Add legend() to control
the built-in legend's placement, columns, title, visibility, and DOM styling.
The legend is available by default when the chart contains named series.
Use show=False to suppress it. If more than one legend component is present,
the last one supplies the effective built-in configuration.
Basic Legend from Named Series
Giving each mark a name= is all it takes — a bare xy.legend() simply opts
into the default placement for the named series.
Position and Title the Legend
loc= moves the legend to a corner such as "upper left", and title= adds a
heading above the entries.
Automatically Avoid Plotted Data
Use loc="best" for an unanchored Cartesian legend that should choose the
least-overlapping standard in-plot position. The browser scores the marks and
important annotations it actually rendered, then rechecks the choice after a
responsive resize or a settled pan/zoom. A concrete location such as
"upper left", an explicit anchor=, and polar legend placement remain fixed.
The initial static choice and the browser's first settled choice take the exact least-occupied candidate, using the canonical location order to break a tie. After that, the browser keeps its settled winner across view, resize, and LOD rechecks unless another candidate improves the normalized occupied fraction by at least 5 percentage points. An empty challenger always replaces an occupied winner, even when that improvement is smaller. This keeps near-uniform plots stable without hiding a clearly open corner.
Multi-Column Layout and Unnamed Series
With many series, ncols=2 lays the entries out in two columns; the dashed
baseline mark has no name=, so it stays out of the legend entirely.
Style the Built-in Legend
class_name and style apply to the legend container. Chart-level
class_names and styles can separately target legend, legend_title,
legend_item, legend_swatch, and legend_label slots. Those are browser DOM
hooks; native SVG and PNG use the legend options and renderable style values
carried in the chart specification.
See Customize Each Part for the stable legend-slot contract.
Supply Framework Content
The positional child or render= value is an opaque replacement object for a
framework adapter:
import reflex as rx
import xy
my_framework_legend = rx.hstack(
rx.box(width="0.75rem", height="0.75rem", background="#6e56cf"),
rx.text("Actual"),
align="center",
spacing="2",
)
chart = xy.line_chart(
xy.line([1, 2, 3], [4, 7, 6], name="Actual"),
xy.legend(render=my_framework_legend),
)
replacement = chart.chrome_components()["legend"]
assert replacement is my_framework_legendCore XY neither imports nor serializes that object. The example is complete,
but it only demonstrates storage: the shipped reflex_xy.chart adapter does
not currently mount custom legend content. A custom adapter can read
chrome_components() and mount the returned component. Standalone HTML keeps
using safe built-in chrome, and the same object is also available through
reflex_components().
Exact parameters and defaults are in Marks and components reference.
API Reference
xy.legend
Configure chart legend chrome.
Props
| Prop | Type | Description |
|---|---|---|
*children | Any | Optional opaque replacement content. |
show | bool | Whether to display the legend. |
loc | Optional[str] | Legend placement within or around the plot. ``"best"`` selects automatic least-overlap placement for an unanchored Cartesian chart; concrete names and ``None`` remain fixed. |
anchor | Optional[tuple[float, ...]] | Two- or four-value normalized plot-coordinate anchor. |
ncols | int | Number of legend columns. |
title | Optional[str] | Optional legend title. |
highlight | bool | Whether hovering a legend entry emphasizes its series by dimming the others (live client only; exports are static). |
toggle | bool | Whether clicking a legend entry hides/shows its series or category (live client only; exports are static). |
render | Any | Opaque renderer supplied by an adapter. |
class_name | Optional[str] | DOM class name applied to the legend. |
style | Optional[dict[str, StyleValue]] | Legend style overrides. |
FAQ
How do I add a legend to a chart in Python?
Give each mark a name=, e.g. xy.line(x, y, name="Actual") — a chart with
named series shows the built-in legend by default. Add xy.legend() only when
you want to configure placement, columns, title, visibility, or styling.
How do I change where the legend appears?
Pass loc= to xy.legend(), e.g. xy.legend(loc="upper right"), or use
xy.legend(loc="best") for content-aware automatic placement. The compatible
loc=None default and every concrete location stay fixed. If more than one
legend() component is present, the last one supplies the effective
configuration.
How do I arrange legend entries in multiple columns?
Set ncols= on the legend, e.g. xy.legend(ncols=2, title="Series"), which
lays the entries out in two columns under an optional legend title.
How do I hide the legend or keep a series out of it?
Use xy.legend(show=False) to suppress the legend entirely. Only marks with a
name= participate in the legend, so omitting name= on a mark keeps that
series out.