Stacked bar chart
A stacked bar chart shows totals broken down into parts. Each bar represents a category (a month, a region, a product), and the bar is split into colored segments showing the sub-categories that make up the total. You get two pieces of information in one chart: how the totals compare, and what each total is made of.
The complication: "stacked bar" is actually three different charts that look similar and answer different questions. Picking the wrong one is the mistake non-technical users make most often.
When to use it
Use a stacked bar when all three are true:
- You have two categorical dimensions and one numeric value. Usually: a main category (month, region), a sub-category (product type, channel), and a quantity (revenue, count).
- The totals are meaningful on their own. The sum of the segments has to be a real thing — total monthly revenue, total headcount, total budget. If the sub-categories don't naturally add up to something, a stacked bar misleads.
- You care about both the total and the parts. If you only care about totals, use a plain bar chart. If you only care about parts across categories, use grouped bars. The stacked version is for when you need both.
Common uses: monthly revenue by product line, headcount by department over time, survey responses by category, traffic sources by month, budget allocation by quarter.
The three variants
These three charts use similar data but answer completely different questions. Pick carefully.
| Variant | What it shows | Use it when... |
|---|---|---|
| Stacked bar | Totals, with sub-category breakdown inside each | The total matters AND the composition matters |
| Grouped bar | Sub-categories side by side, no totals shown | You want to compare sub-categories across main categories |
| 100% stacked bar | Proportions only — every bar is the same height | You only care about composition, not totals |
A concrete example with the same data:
- Stacked: "Total Q3 revenue was $2.1M, of which $1.2M was from North America." — Totals and mix both visible.
- Grouped: "North America revenue grew from $1.0M to $1.2M while EMEA stayed flat." — Regional comparison is clean, but you can't easily see the company total.
- 100% stacked: "North America went from 48% of revenue to 57% of revenue." — Mix shifts are obvious, but you can't see if the business grew or shrank overall.
The biggest mistake is using a 100% stacked bar when you actually wanted a regular stacked bar. Readers think they're seeing growth when they're only seeing proportional shift — the bars are all the same height by design, so a company that halved in size still looks stable.
Example data
Stacked bar data is usually in long form — one row per combination of main category and sub-category, with the value as a third column. Here's quarterly revenue by product line for an imaginary software company:
| Quarter | Product line | Revenue ($k) |
|---|---|---|
| Q1 | Core app | 820 |
| Q1 | Add-ons | 310 |
| Q1 | Services | 180 |
| Q2 | Core app | 890 |
| Q2 | Add-ons | 380 |
| Q2 | Services | 210 |
| Q3 | Core app | 940 |
| Q3 | Add-ons | 460 |
| Q3 | Services | 240 |
| Q4 | Core app | 1,020 |
| Q4 | Add-ons | 580 |
| Q4 | Services | 280 |
When you plot this as a stacked bar (quarter on the x-axis, revenue on the y-axis, color by product line), you can see at a glance that total revenue is growing quarter over quarter, and that Add-ons is the fastest-growing segment. A plain bar chart of totals would hide the second story; a grouped bar chart would obscure the totals.
Spreadsheets sometimes expect this data in wide form instead — one row per quarter, one column per product line:
| Quarter | Core app | Add-ons | Services |
|---|---|---|---|
| Q1 | 820 | 310 | 180 |
| Q2 | 890 | 380 | 210 |
| Q3 | 940 | 460 | 240 |
| Q4 | 1,020 | 580 | 280 |
Both contain the same information. Excel and Google Sheets want wide form; most code libraries want long form and pivot internally.
How to read it
Scan in this order:
- Look at the total heights. Which bars are tallest? Which are shortest? That's your "totals" story — how the main category compares overall.
- Look at the bottom segment. Because it sits on the baseline, you can compare its size across bars accurately — this is the only segment where visual comparison is reliable.
- Look at the overall color pattern. Has one color taken over more bars? A color that grows steadily across bars shows a rising sub-category.
The thing not to do: try to compare segment sizes that aren't on the baseline. Because the middle and top segments "float" at different heights, comparing a middle segment in Q1 to a middle segment in Q4 requires mental subtraction. Your eyes aren't good at this, and readers get it wrong.
If your main story is about a non-bottom segment, either reorder the stack to put that segment on the bottom, or switch to a grouped bar chart.
Stacked bar vs. grouped bar — which to use?
This is the everyday decision. A simple rule:
- Stacked if the total is part of the story. "Revenue grew, driven by add-ons" requires seeing both.
- Grouped if you're comparing sub-categories. "Add-ons outgrew core app" is clearer with sub-categories side by side on the same baseline.
Put side by side, grouped bars are easier to compare exactly but take more horizontal space. Stacked bars are more compact but only the bottom segment compares cleanly. If you're unsure, try both — the right chart usually becomes obvious once you see them.
How to build one
In a spreadsheet (Excel or Google Sheets)
- Arrange your data in wide form (main category in column A, sub-categories in columns B onward, as shown above).
- Select the whole table including headers.
- Excel: Insert → Charts → Stacked Column (or Stacked Bar for horizontal). Same menu has 100% Stacked variants.
- Google Sheets: Insert → Chart → Chart type → Stacked bar or Stacked column.
- To switch between stacked, grouped, and 100% stacked, change the chart type — the data doesn't change.
For horizontal bars (useful when sub-categories have long names), use "Stacked Bar" in Excel or "Stacked bar chart" in Sheets.
With code (for a dashboard or report)
Most libraries want the long form shown above. The pattern is almost identical across libraries — you specify which column is the x-axis, which is the stack group, and which is the value.
// Long form — what Plotly, Recharts, Observable Plot, ggplot expect
const data = [
{ quarter: "Q1", product: "Core app", revenue: 820 },
{ quarter: "Q1", product: "Add-ons", revenue: 310 },
{ quarter: "Q1", product: "Services", revenue: 180 },
{ quarter: "Q2", product: "Core app", revenue: 890 },
// ... etc.
];
// Switching variants is usually one config option:
// stack: true → stacked bar
// stack: false → grouped bar
// stack: "percent" → 100% stacked bar
Keep the data shape constant and change the config to switch variants. This makes it easy to A/B test which variant tells your story best without re-shaping data.
Tips
- Keep the number of segments small. Three to five sub-categories per bar is the sweet spot. With ten, the segments become thin stripes and the color legend overwhelms the chart. Aggregate small categories into "Other."
- Order the stack meaningfully. Put the largest or most important segment on the bottom where it's easiest to read. Don't let the chart tool order them alphabetically.
- Use consistent colors across related charts. If "Core app" is blue in one chart, it should be blue in every chart on the same page. Nothing confuses a reader faster than "Add-ons" being green in one chart and orange in the next.
- Add total labels to stacked bars. If the total is part of the story, label it at the top of each bar. Readers shouldn't have to estimate from the axis.
- Don't use 100% stacked bars for only two sub-categories. A 100% stacked bar with two segments is just showing a percentage — a plain line chart of "percent A" is clearer and takes less space.
- Watch for negative values. Stacked bars break when sub-categories include negatives (e.g., profit by region where some regions lost money). Diverging bar charts or waterfall charts handle this better.