liveBook · Manning

Stacked bar chart

As explained in D3.js in Action, Third Edition

A stacked bar chart represents multiple series within each bar by vertically or horizontally adjoining segments whose combined extent encodes a total.

A stacked bar chart divides each bar into adjoining series segments. The full bar shows a total, while its segments show category contributions; it is often used to show how trends evolve over time. section 5.2.2

In D3, build the chart as a preprocessing-and-drawing pipeline. A stack layout takes the original data and returns annotated series with a lower boundary d[0] and upper boundary d[1] for every segment. Bind each series to SVG rectangles, then use those boundaries to position and size the rectangles. section 5.0 section 5.4

Build a basic chart in this order:

  • Initialize d3.stack() and provide the data keys that identify the series to stack. section 5.4
  • Run the stack generator on the dataset and retain its annotated series. section 5.2
  • Create a band scale for bar positions and a linear y-scale spanning zero to the maximum upper boundary. section 5.2.2
  • For each series, join its values to rect elements; map x to the category, y to d[1], and height to yScale(d[0]) minus yScale(d[1]). section 5.2.2
  • Add inner band padding and axes to separate bars and make values readable. section 5.2.2

Music-format sales by year

Use one bar per year and one segment per music format. A shared band scale aligns yearly positions with related charts, while a color scale distinguishes formats. The top edge of each complete bar represents the combined sales for that year. section 5.0 section 5.1.1 section 5.2.2

Stack order and offset change both appearance and interpretation. The default offset places shapes above zero; diverging separates positive and negative values, and expand converts each stack to a 0–1, 100% comparison. Recalculate the y-scale domain whenever an order or offset changes the boundaries. section 5.2.4 section 5.4

Listing 5.7 Appending the stacked bars (stacked-bars.js)
annotatedData.forEach(series => {  #1

  innerChart
    .selectAll(`.bar-${series.key}`)           
    .data(series)                               #2
    .join("rect")                             
      .attr("class", d => `bar-${series.key}`) 

      .attr("x", d => xScale(d.data.year))             
      .attr("y", d => yScale(d[1]))                    
      .attr("width", xScale.bandwidth())               
      .attr("height", d => yScale(d[0]) - yScale(d[1])) 
      .attr("fill", colorScale(series.key));             

});

This rectangle join makes the boundary-to-geometry mapping visible: the upper boundary sets y, and the difference between boundaries sets height. section 5.2.2

How D3.js in Action, Third Edition covers it

How deep it goes
Walks through stack output, scales, rectangle joins, axes, and order or offset effects.
Examples
Uses music-format sales by year and a rectangle data join to construct the chart.
What it assumes
Assumes familiarity with CSV loading, D3 scales, SVG groups, and data binding.
What you can do after
Build it from scratch with d3.stack(), D3 scales, SVG rectangles, axes, and configurable order or offset.
How it connects
Connects D3 stack layouts with streamgraphs, band scales, linear scales, SVG rectangles, axes, and legends.

Also explained in

Compare how 5 books explain stacked bar chart →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of D3.js in Action, Third Edition. The section links point to the parts of the book it draws on.