Vizro Chart Best Practices
Chart Selection
| Data question | Chart | | ----------------------- | --------------------------- | | Compare categories | Bar (horizontal preferred) | | Trend over time | Line (12+ points) | | Part-to-whole (simple) | Pie/donut (2–5 slices only) | | Part-to-whole (complex) | Stacked bar | | Distribution | Histogram or box | | Correlation | Scatter |
Never use: 3D charts, pie with 6+ slices, dual Y-axis, bar charts not starting at zero.
Plotly Conventions
- Plotly Express does not aggregate. Pre-aggregate in
app.pyor custom chart functions. - Bar: sort by value (largest→smallest) unless time-based; always start at zero.
- Line: pre-aggregate and sort by x ascending.
- Remove axis title when ticks are self-explanatory. Remove legend title (keep items only).
Color Rules
- Plotly charts & KPI cards: Do not specify colors — no
marker_color, hex codes,color_discrete_map, orcolor_discrete_sequence. This applies even for categories with apparent semantic meaning. Only override when the user explicitly asks. - AG Grid: Does not pick up Vizro template colors automatically. Use
from vizro.themes import palettes, colorsfor cell styling. - See chart-best-practices.md for palette names and import patterns.
Custom Charts (@capture("graph"))
Use when: aggregation/sorting needed, update_layout()/update_traces() calls, reference lines, parameter-driven logic, dual-axis, multi-trace go.Figure(), shared legend control.
In practice, most bar and line charts need @capture("graph") functions that aggregate data inside. Inline px.bar(data_frame="raw", x="region", y="revenue") on detail-level data stacks individual rows as separate rectangles instead of summing — producing visually broken charts.
KPI Cards
- Use built-in
kpi_card/kpi_card_referencefromvizro.figuresinFiguremodel. - Never rebuild KPI cards as custom charts. Exception: strictly impossible with built-in (e.g. dynamic text).
- Titles go in figure args (
_target_: kpi_card→title:), not on the component.
Tables
- Use
vm.AgGridwithfigure=dash_ag_grid(data_frame=...)fromvizro.tables. AG Grid is the only table component you should write. - Never use
vm.Table/ Dash DataTable. Never fake a table with Plotly (heatmap-with-text,px.imshowannotated as a table, scatter-with-text). Even small tables go in AG Grid; KPI cards or a horizontal bar chart are the only acceptable lighter alternatives. - For custom column logic, write
@capture("ag_grid")withdata_frameas the exact DataFrame argument name (notdf, notdata). - See the dashboard-build skill's example_ag_grid.py for the two canonical patterns (drop-in factory +
@capture("ag_grid")for runtime-parameterized grids) and the Dash AG Grid / JS AG Grid knowledge-mapping notes.
Deep Dive
Load chart-best-practices.md when you need: extended chart type decision tree, Plotly Express formatting conventions (100% stacked bar, axis/legend cleanup), palette/color names and use cases, accessibility rules, or detailed @capture("graph") guidance.