Comparison

Bar chart

Use a bar chart to compare a single measure across categories, like revenue by region or signups by plan. Bar length is one of the most accurately perceived visual encodings, so it works well even with a dozen or more categories. Reach for a line chart instead when the categories are actually points in time.

Minimal dvt spec

The panel body for a bar chart. Add an id and title of your own; the sample data is inline, so it renders the moment you paste it into a dvt dashboard. Point it at your warehouse by swapping that sample data for a data block whose query returns the same shape.

View spec
{
  "type": "chart:bar",
  "data": {
    "rows": [
      {
        "month": "Jan",
        "revenue": 120
      },
      {
        "month": "Feb",
        "revenue": 150
      },
      {
        "month": "Mar",
        "revenue": 178
      },
      {
        "month": "Apr",
        "revenue": 168
      },
      {
        "month": "May",
        "revenue": 212
      },
      {
        "month": "Jun",
        "revenue": 264
      }
    ]
  },
  "spec": {
    "series": [
      {
        "type": "bar",
        "barMaxWidth": 48
      }
    ]
  }
}

Customize

Every control in dvt's edit tray writes a field of this spec; the variants below change the minimal spec above, and the reference below lists every control and ChartSpec field this type accepts.

Data labels

Print the value on top of every bar, formatted as compact currency.

What changed
 {
   "type": "chart:bar",
   "data": {
     "rows": [
       {
         "month": "Jan",
         "revenue": 120
       },
       {
         "month": "Feb",
         "revenue": 150
       },
       {
         "month": "Mar",
         "revenue": 178
       },
       {
         "month": "Apr",
         "revenue": 168
       },
       {
         "month": "May",
         "revenue": 212
       },
       {
         "month": "Jun",
         "revenue": 264
       }
     ]
   },
   "spec": {
     "series": [
       {
         "type": "bar",
         "barMaxWidth": 48
       }
-    ]
+    ],
+    "label": {
+      "show": true,
+      "position": "top",
+      "format": {
+        "type": "currency",
+        "currency": "USD",
+        "decimals": 0,
+        "compact": true
+      }
+    }
   }
 }
Full spec
{
  "type": "chart:bar",
  "data": {
    "rows": [
      {
        "month": "Jan",
        "revenue": 120
      },
      {
        "month": "Feb",
        "revenue": 150
      },
      {
        "month": "Mar",
        "revenue": 178
      },
      {
        "month": "Apr",
        "revenue": 168
      },
      {
        "month": "May",
        "revenue": 212
      },
      {
        "month": "Jun",
        "revenue": 264
      }
    ]
  },
  "spec": {
    "series": [
      {
        "type": "bar",
        "barMaxWidth": 48
      }
    ],
    "label": {
      "show": true,
      "position": "top",
      "format": {
        "type": "currency",
        "currency": "USD",
        "decimals": 0,
        "compact": true
      }
    }
  }
}

Target band

Mark a target range and the series average with a band and a line.

What changed
 {
   "type": "chart:bar",
   "data": {
     "rows": [
       {
         "month": "Jan",
         "revenue": 120
       },
       {
         "month": "Feb",
         "revenue": 150
       },
       {
         "month": "Mar",
         "revenue": 178
       },
       {
         "month": "Apr",
         "revenue": 168
       },
       {
         "month": "May",
         "revenue": 212
       },
       {
         "month": "Jun",
         "revenue": 264
       }
     ]
   },
   "spec": {
     "series": [
       {
         "type": "bar",
         "barMaxWidth": 48
       }
+    ],
+    "annotations": [
+      {
+        "type": "band",
+        "axis": "y",
+        "from": 150,
+        "to": 200,
+        "label": "Target range"
+      },
+      {
+        "type": "line",
+        "axis": "y",
+        "stat": "avg",
+        "of": "revenue",
+        "label": "Average"
+      }
     ]
   }
 }
Full spec
{
  "type": "chart:bar",
  "data": {
    "rows": [
      {
        "month": "Jan",
        "revenue": 120
      },
      {
        "month": "Feb",
        "revenue": 150
      },
      {
        "month": "Mar",
        "revenue": 178
      },
      {
        "month": "Apr",
        "revenue": 168
      },
      {
        "month": "May",
        "revenue": 212
      },
      {
        "month": "Jun",
        "revenue": 264
      }
    ]
  },
  "spec": {
    "series": [
      {
        "type": "bar",
        "barMaxWidth": 48
      }
    ],
    "annotations": [
      {
        "type": "band",
        "axis": "y",
        "from": 150,
        "to": 200,
        "label": "Target range"
      },
      {
        "type": "line",
        "axis": "y",
        "stat": "avg",
        "of": "revenue",
        "label": "Average"
      }
    ]
  }
}

Conditional colors

Recolor bars above a threshold and apply a named palette to the rest.

What changed
 {
   "type": "chart:bar",
   "data": {
     "rows": [
       {
         "month": "Jan",
         "revenue": 120
       },
       {
         "month": "Feb",
         "revenue": 150
       },
       {
         "month": "Mar",
         "revenue": 178
       },
       {
         "month": "Apr",
         "revenue": 168
       },
       {
         "month": "May",
         "revenue": 212
       },
       {
         "month": "Jun",
         "revenue": 264
       }
     ]
   },
   "spec": {
     "series": [
       {
         "type": "bar",
         "barMaxWidth": 48
       }
-    ]
+    ],
+    "colorRules": [
+      {
+        "when": {
+          "field": "revenue",
+          "op": "gte",
+          "value": 200
+        },
+        "color": "#1F9E96"
+      }
+    ],
+    "palette": "okabe-ito"
   }
 }
Full spec
{
  "type": "chart:bar",
  "data": {
    "rows": [
      {
        "month": "Jan",
        "revenue": 120
      },
      {
        "month": "Feb",
        "revenue": 150
      },
      {
        "month": "Mar",
        "revenue": 178
      },
      {
        "month": "Apr",
        "revenue": 168
      },
      {
        "month": "May",
        "revenue": 212
      },
      {
        "month": "Jun",
        "revenue": 264
      }
    ]
  },
  "spec": {
    "series": [
      {
        "type": "bar",
        "barMaxWidth": 48
      }
    ],
    "colorRules": [
      {
        "when": {
          "field": "revenue",
          "op": "gte",
          "value": 200
        },
        "color": "#1F9E96"
      }
    ],
    "palette": "okabe-ito"
  }
}

Axis polish

Name both axes, rotate the x labels, and add dashed gridlines at a tighter density.

What changed
 {
   "type": "chart:bar",
   "data": {
     "rows": [
       {
         "month": "Jan",
         "revenue": 120
       },
       {
         "month": "Feb",
         "revenue": 150
       },
       {
         "month": "Mar",
         "revenue": 178
       },
       {
         "month": "Apr",
         "revenue": 168
       },
       {
         "month": "May",
         "revenue": 212
       },
       {
         "month": "Jun",
         "revenue": 264
       }
     ]
   },
   "spec": {
     "series": [
       {
         "type": "bar",
         "barMaxWidth": 48
       }
-    ]
+    ],
+    "xAxis": {
+      "name": "Month",
+      "axisLabel": {
+        "rotate": 30
+      }
+    },
+    "yAxis": {
+      "name": "Revenue ($k)",
+      "axisLabel": {
+        "format": {
+          "type": "number",
+          "decimals": 0,
+          "compact": true
+        }
+      }
+    },
+    "gridlines": {
+      "y": {
+        "show": true,
+        "style": "dashed"
+      }
+    },
+    "density": "compact"
   }
 }
Full spec
{
  "type": "chart:bar",
  "data": {
    "rows": [
      {
        "month": "Jan",
        "revenue": 120
      },
      {
        "month": "Feb",
        "revenue": 150
      },
      {
        "month": "Mar",
        "revenue": 178
      },
      {
        "month": "Apr",
        "revenue": 168
      },
      {
        "month": "May",
        "revenue": 212
      },
      {
        "month": "Jun",
        "revenue": 264
      }
    ]
  },
  "spec": {
    "series": [
      {
        "type": "bar",
        "barMaxWidth": 48
      }
    ],
    "xAxis": {
      "name": "Month",
      "axisLabel": {
        "rotate": 30
      }
    },
    "yAxis": {
      "name": "Revenue ($k)",
      "axisLabel": {
        "format": {
          "type": "number",
          "decimals": 0,
          "compact": true
        }
      }
    },
    "gridlines": {
      "y": {
        "show": true,
        "style": "dashed"
      }
    },
    "density": "compact"
  }
}

Everything you can set

ControlLayerWhere it lands
Data
Chart typeCoretype
Series typeCoretype
Category columnCorespec.categoryField
Measure columnCorespec.series[]
Style
Series colorsCoreoverrides.chart.series.1
Bar widthEChartsspec.series[].barWidth
Color schemeCorespec.palette
Conditional colorsCorespec.colorRules
Labels
Show legendEChartsspec.legend.show
Legend positionEChartsspec.legend.position
Show data labelsCorespec.label.show
Label positionCorespec.label.position
FormatCorespec.label.format
Label valueCorespec.label.derive
RotateCorespec.label.rotate
Font sizeCorespec.label.fontSize
Label colorCorespec.label.color
TooltipCorespec.tooltip
Axes
X-axis nameCorespec.xAxis.name
Y-axis nameCorespec.yAxis.name
Y-axis minCorespec.yAxis.min
Y-axis maxCorespec.yAxis.max
Y-axis scaleCorespec.yAxis.type
X-axis label rotateCorespec.xAxis.axisLabel.rotate
X-axis label sizeCorespec.xAxis.axisLabel.fontSize
Y-axis label sizeCorespec.yAxis.axisLabel.fontSize
X-axis label spacingCorespec.xAxis.axisLabel.margin
X-axis formatCorespec.xAxis.axisLabel.format
Y-axis formatCorespec.yAxis.axisLabel.format
X-axis gridlinesCorespec.gridlines.x.show
Y-axis gridlinesCorespec.gridlines.y.show
Plot densityCorespec.density
Advanced
Boundary gapCorespec.xAxis.boundaryGap
AnnotationsCorespec.annotations

Chart spec fields

Every chart type accepts these ChartSpec fields. Most are dvt spec fields the renderer compiles for you. grid passes straight through to ECharts; series mixes ECharts series options with dvt's dataField; and any key on xAxis, yAxis, legend, or tooltip that is not a documented dvt key passes through too.

FieldWhat it does
xAxisOne axis, or an array of axes, via AxisSpec: type, name, min, max, scale, log, and label formatting.
yAxisSame shape as xAxis, for the value axis: type, name, min, max, scale, log, and label formatting.
seriesPer-series overrides: type, dataField, name, stack, smooth, itemStyle, lineStyle, areaStyle, label.
legendShow or hide the legend, set its position, and format an aggregated value shown next to each entry.
tooltipChoose which fields appear, a totals row, field order, a custom template, and crosshair behavior.
gridA raw ECharts grid box (left, right, top, bottom, containLabel), passed through unmodified.
funnelRateShow a conversion-rate label on a funnel: step, overall, total, or none, with a precision.
labelData labels: show, position, format, a derived value (percent of total, delta), rotation, size, color.
gridlinesToggle and style gridlines per axis: show, dashed or solid style, width, and color.
bandingAlternating background bands along one axis, to make long rows or columns easier to scan.
plotAreaSet the plot area's background fill and border color.
gridPaddingExplicit left, right, top, and bottom padding around the plot area, each a number or a string.
densityOverall plot density: comfortable (default spacing) or compact (tighter margins).
paletteName a registered color scheme to apply to the series, instead of the default categorical colors.
categoryColorsMap specific category values to explicit colors, overriding the palette for just those categories.
colorRulesApply a color to a data point the first time one of its ordered when conditions matches.
colorScaleA continuous color scale (sequential, diverging, or piecewise) with a scheme, domain, and buckets.
annotationsFixed or computed reference lines, bands, points, or text, placed at an axis value or a stat of a field.
trendlineOverlay a fitted trend line: true for a default linear fit, or an object naming the method and order.
footnotesUp to 50 footnote entries, each a marker plus explanatory text, rendered below the chart.
sourceNoteA single line of source-attribution text rendered below the chart.

Build it in dvt

Every chart type on this site is a few lines of the same declarative JSON spec. Read the full spec format, or connect an AI agent to your warehouse and build one live in the quickstart.

Follow the build

dvt is in founding research. Leave your email and we'll reach out when there's something to see — no newsletters, no noise.

No spam. We use this to reach out directly, nothing else.