---
url: https://chartbuddy.io/embed/docs/chart-types/clustered-bar.md
---
# Clustered bar

Side-by-side bars that compare series within each category.

## Identity

| | |
|---|---|
| `chartType` | `clusteredBar` |
| Option bag | `bar` |
| `seriesData` layout | `seriesRows` – row 0 = category header; later rows = series |
| Min grid | 2 rows × 2 columns (header included) |
| Orientation | Yes – `vertical` (default) or `horizontal` |
| Sample | [Clustered bar](/samples/clustered-bar) · [Horizontal bar](/samples/horizontal-bar) |

***

## Minimal `chartData`

```js
{
  chartType: 'clusteredBar',
  isDataTransposed: true,
  seriesData: [
    ['', 'Q1', 'Q2', 'Q3', 'Q4'],
    ['Revenue', 100, 112, 125, 140],
    ['Costs', 60, 66, 70, 78],
  ],
  title: { visible: true, text: 'Revenue vs Costs' },
  subtitle: { visible: false, text: '' },
}
```

***

## `seriesData`

With `isDataTransposed: true` (usual):

```js
[
  ['', 'Q1', 'Q2', 'Q3'],       // categories
  ['Revenue', 100, 112, 125],   // series 0
  ['Costs', 60, 66, 70],        // series 1
]
```

| Rule | Detail |
|---|---|
| Row 0 | Category labels (after the corner cell) |
| Later rows | One series each; first cell is the series name |
| Cells | `string \| number \| boolean \| null` |
| Ragged rows | Warn, still load – pad when columns must align |

Shared layout rules: [chartData schema · seriesData](/api/chart-data#seriesdata-layouts).

***

## Option bag: `bar`

`clusteredBar`, `stackedBar`, and `stackedBar100` all read **`cd.bar`**. Stacking / 100% behaviour comes from `chartType`, not from a different bag.

| Field | Default (new charts) | Role |
|---|---|---|
| `padding` | `0.3` | Gap between bars / clusters, `0–1` |
| `cornerRadius` | `0` | Bar corner radius (px) |
| `reverseStackOrder` | `false` | Stack order (mainly stacked types; harmless on clustered) |
| `seriesStrokes` / `seriesStrokeWidths` / `seriesStrokeDashArrays` | `[]` | Per-series stroke chrome |
| `series` | `[]` | Per-series / per-point override slots |
| `overrides` | – | Indexed style patches |

```js
{
  chartType: 'clusteredBar',
  seriesData: [/* … */],
  bar: {
    padding: 0.2,
    cornerRadius: 2,
  },
}
```

***

## Axes & scales

| Role | Vertical (default) | Horizontal |
|---|---|---|
| Domain (categories) | `bottom` | `left` |
| Primary range (values) | `left` | `bottom` |

* Keep **0 in range** for honest bar lengths (engine bias for bars).
* Format / tick interval / gridlines on the **primary range** side after orientation.
* Secondary axis is uncommon on pure clustered bars; use [combo](/chart-types/combo) or [dual-axis line](/samples/dual-axis-line) when units differ.

Details: [Axes · by chart type](/axes/by-chart-type) · [Value axis](/axes/value-axis) · [Orientation](/concepts/orientation).

### Horizontal

```js
{
  chartType: 'clusteredBar',
  orientation: 'horizontal',
  isDataTransposed: true,
  seriesData: [/* same layout */],
  title: { visible: true, text: 'Pageview Sources' },
  subtitle: { visible: false, text: '' },
  legend: { visible: false },
}
```

After the flip, put value formats and `preferredTickInterval` on `axes.bottom`, not `axes.left`. Live: [Horizontal bar sample](/samples/horizontal-bar).

***

## Type-specific behaviour

* Palette lives on `legend.colors`, not on the `bar` bag.
* Data labels / series emphasis are mostly annotation and override trees – polish in the editor, then `getChartData()`.
* Changing to `stackedBar` / `stackedBar100` keeps the same `seriesData` shape and the same `bar` bag; only the type (and axis % defaults for 100%) change.

***

## Pitfalls

* Using the `line` or `area` bag on a bar chart – rejected as `foreign-option-bag`
* Formatting `axes.left` after setting `orientation: 'horizontal'` (range moved to `bottom`)
* Pinning `customMin` above zero so bars look taller than the data
* Expecting `reverseStackOrder` to change clustered side-by-side order in a meaningful way – it targets stacks
* Wrong `seriesData` orientation (`isDataTransposed: false`) without matching the grid

***

## Related

* [Stacked bar / 100%](/chart-types/stacked-bar) · [Combo](/chart-types/combo)
* [chartData schema](/api/chart-data) · [Axes](/axes/) · [Legend](/configuration/legend)
* Samples: [Clustered bar](/samples/clustered-bar) · [Horizontal bar](/samples/horizontal-bar) · [Currency ticks](/samples/currency-ticks)
