Facet Charts and Layered Marks in Python

When to Use

Layer marks in a neutral chart() container when they share a coordinate system. Use facet_chart() to repeat one composition across categories — a facet chart (also called a facet plot, or simply small multiples) draws each category in its own panel.

Live Demo

The live example layers different mark types in one coordinate system.

Chart Types

Layered Marks

Use a neutral chart() container to layer different marks in one coordinate system. Declare broad fills first, followed by lines, points, and annotations.

Facet Chart

Regional trends

cols controls wrapping, gap controls panel spacing, and shared axes keep categories and numeric domains comparable. Each panel retains the same per-mark decimation and aggregation behavior as a standalone chart.

Marks render in declaration order, so put broad fills first and then lines or points. Annotations are composed separately from the mark trace order as data-aligned chart chrome; see the annotation guide for rules, bands, labels, and callouts.

Ordered Layers with a Legend

Declaration order is the z-order — this composition stacks an area fill, a dashed forecast line, a solid actuals line with scatter markers, and an hline goal, with name= on each mark feeding a positioned legend:

Expected Data Shape

Layered marks may share chart-level data= or use their own sources, but they must resolve into compatible axes. facet_chart takes a table plus a by column whose distinct values define panels.

Key Options

Layered charts use the ordinary mark and chart options. Facets add by, cols, gap, share_x, and share_y; each panel keeps its own chart payload and the same per-mark representation rules.

API Reference

xy.chart

A neutral single-panel chart for overlays and mixed mark composition.

Props

PropTypeDescription
*childrenComponent

Marks, axes, annotations, and chart chrome.

titleOptional[str]

Title shown above the plot.

widthint | str

Chart width in pixels or a CSS size such as ``"100%"``.

heightint | str

Chart height in pixels or a CSS size such as ``"100%"``.

paddingUnion[float, Sequence[float], None]

Plot margins, as one value or a sequence of side values. Use zero for an edge-to-edge sparkline.

dataTableLike

Chart-level data used by marks that omit their own ``data``.

class_nameOptional[str]

CSS class applied to the chart container.

class_namesOptional[dict[str, str]]

CSS classes keyed by stable chart DOM slot.

styleOptional[dict[str, StyleValue]]

Inline style overrides for the chart container.

stylesOptional[dict[str, dict[str, StyleValue]]]

Inline style mappings keyed by stable chart DOM slot.

on_hoverOptional[Callable[[dict], None]]

Callback receiving hover event payloads.

on_clickOptional[Callable[[dict], None]]

Callback receiving picked-mark click payloads.

on_brushOptional[Callable[[dict], None]]

Callback receiving brush event payloads.

on_selectOptional[Callable[[Selection], None]]

Callback receiving data-space selections.

on_view_changeOptional[Callable[[dict], None]]

Callback receiving viewport change payloads.

hoverOptional[bool]

Whether pointer movement emits hover events.

clickOptional[bool]

Whether picked marks emit click events.

selectOptional[bool]

Whether shift-drag box selection is enabled.

brushOptional[bool]

Whether brush selection is enabled.

crosshairOptional[bool]

Whether plot-aligned hover guides are shown.

navigationOptional[bool]

Whether browser pan and zoom navigation is enabled.

panOptional[bool]

Whether plain-drag panning is enabled.

pan_axesOptional[tuple[str, ...]]

Declared axis IDs translated by pan gestures.

zoomOptional[bool]

Whether viewport zoom is enabled.

default_drag_actionOptional[DefaultDragAction]

Initial action performed by a plain plot drag.

zoom_axesOptional[tuple[str, ...]]

Declared axis IDs changed by zoom gestures and controls.

zoom_limitsOptional[ZoomLimits]

Minimum and maximum magnification globally or by axis.

wheel_zoomOptional[bool]

Whether wheel and trackpad zoom is available.

box_zoomOptional[bool]

Whether box zoom is available as a drag action.

zoom_buttonsOptional[bool]

Whether modebar Zoom In/Out commands are available.

double_click_resetOptional[bool]

Whether double-click restores ``reset_axes``.

reset_axesOptional[tuple[str, ...]]

Declared axis IDs restored by reset.

link_groupOptional[str]

Identifier used to synchronize charts in the browser.

link_axesOptional[tuple[str, ...]]

Axes synchronized within the link group.

xy.facet_chart

Repeat the child mark composition once per value of ``by``.

Props

PropTypeDescription
*childrenComponent

Marks, axes, annotations, and chart chrome for each panel.

byUnion[str, ArrayLike, None]

Facet values or a column name resolved from chart-level data.

colsint

Maximum number of panel columns.

share_xbool

Whether panels share an x domain.

share_ybool

Whether panels share a y domain.

linkOptional[Union[str, bool]]

Runtime-linked axes: ``True``/``"both"`` for both axes, ``"x"`` or ``"y"`` for one axis, and ``False``/``None`` to disable.

link_selectbool

Whether data-space selections are echoed across panels.

gapint

Gap between panels in pixels.

titleOptional[str]

Title shown above the plot.

widthint | str

Chart width in pixels or a CSS size such as ``"100%"``.

heightint | str

Chart height in pixels or a CSS size such as ``"100%"``.

paddingUnion[float, Sequence[float], None]

Plot margins, as one value or a sequence of side values. Use zero for an edge-to-edge sparkline.

dataTableLike

Chart-level data used by marks that omit their own ``data``.

class_nameOptional[str]

CSS class applied to the chart container.

class_namesOptional[dict[str, str]]

CSS classes keyed by stable chart DOM slot.

styleOptional[dict[str, StyleValue]]

Inline style overrides for the chart container.

stylesOptional[dict[str, dict[str, StyleValue]]]

Inline style mappings keyed by stable chart DOM slot.

on_hoverOptional[Callable[[dict], None]]

Callback receiving hover event payloads.

on_clickOptional[Callable[[dict], None]]

Callback receiving picked-mark click payloads.

on_brushOptional[Callable[[dict], None]]

Callback receiving brush event payloads.

on_selectOptional[Callable[[Selection], None]]

Callback receiving data-space selections.

on_view_changeOptional[Callable[[dict], None]]

Callback receiving viewport change payloads.

hoverOptional[bool]

Whether pointer movement emits hover events.

clickOptional[bool]

Whether picked marks emit click events.

selectOptional[bool]

Whether shift-drag box selection is enabled.

brushOptional[bool]

Whether brush selection is enabled.

crosshairOptional[bool]

Whether plot-aligned hover guides are shown.

navigationOptional[bool]

Whether browser pan and zoom navigation is enabled.

panOptional[bool]

Whether plain-drag panning is enabled.

pan_axesOptional[tuple[str, ...]]

Declared axis IDs translated by pan gestures.

zoomOptional[bool]

Whether viewport zoom is enabled.

default_drag_actionOptional[DefaultDragAction]

Initial action performed by a plain plot drag.

zoom_axesOptional[tuple[str, ...]]

Declared axis IDs changed by zoom gestures and controls.

zoom_limitsOptional[ZoomLimits]

Minimum and maximum magnification globally or by axis.

wheel_zoomOptional[bool]

Whether wheel and trackpad zoom is available.

box_zoomOptional[bool]

Whether box zoom is available as a drag action.

zoom_buttonsOptional[bool]

Whether modebar Zoom In/Out commands are available.

double_click_resetOptional[bool]

Whether double-click restores ``reset_axes``.

reset_axesOptional[tuple[str, ...]]

Declared axis IDs restored by reset.

link_groupOptional[str]

Identifier used to synchronize charts in the browser.

link_axesOptional[tuple[str, ...]]

Axes synchronized within the link group.

FAQ

How do I make small multiples (facets) in Python?

Use xy.facet_chart(...) with a by= column; xy repeats the composition once per distinct value and lays the panels out on a grid you control with cols, one small facet graph per category.

How do I layer multiple chart types together?

Add several marks to a neutral xy.chart(...) container. They render in declaration order, so put broad fills first, then lines, points, and annotations.

How do I keep axes consistent across facet panels?

Set share_x=True and share_y=True so every panel uses the same numeric and categorical domains for direct comparison.

Do faceted charts stay interactive?

Yes. Each panel keeps the same per-mark decimation and aggregation as a standalone chart, so pan, zoom, and hover work in every panel.

Built with Reflex