Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

To plot one value for each category in D3, use a band scale for the category positions and a quantitative scale for bar heights. To compare several values within each category, use grouped bars: an outer band scale positions categories, an inner band scale positions series within each category, and a nested data join creates the bars.

First decide what “multiple columns” means

In a bar chart, “multiple columns” can mean either many category bars, with one value per category, or several bars for each category, with one bar for each measure. The first layout needs a single band scale for categories. The second is a grouped bar chart and needs an additional band scale for series.

D3 is “The JavaScript library for bespoke data visualization,” according to Observable’s D3 homepage. Its scales, selections, and axes are the building blocks for either layout.

Plot one bar for each category

Use d3.scaleBand to assign each category a horizontal position and a bar width. Use a quantitative scale such as d3.scaleLinear to map numeric values to vertical positions. A band scale is designed for categorical positions and gives bars a width; a point scale has no bandwidth and is generally more suitable for point positions than rectangles. See the band scale reference and linear scale reference.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Set the band scale’s domain to the category names and its range to the chart’s inner horizontal area. Set the linear scale’s domain to include the plotted values and its range from the bottom of the plot to the top. Because SVG’s y coordinates increase downward, mapping larger values toward the top means using a range that runs from the plot bottom to the plot top.

Generate an x axis from the band scale and a y axis from the quantitative scale. The D3 axis documentation describes axis generators. Leave space around the plotting area for tick labels and axis titles, following the margin convention in the D3 getting-started guide.

Plot several measures per category with grouped bars

For grouped bars, use one scale to position categories and another to position each measure within its category. Bind each category’s measure values to a set of rectangles nested inside that category’s group. D3’s data-joining documentation covers nested joins, including matrix-style data structures.

Prepare data with named values

Keep category labels and measure names explicit. For example:

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
const data = [
  { category: "A", apples: 12, oranges: 8 },
  { category: "B", apples: 7, oranges: 15 }
];
const series = ["apples", "oranges"];

Each row represents a category; each named field represents a series. If the data comes from CSV, remember that parsed fields are text unless converted. Convert numeric fields before calculating a y-domain or drawing bars, and check that every row has the expected category and values.

Build outer and inner band scales

Give the outer x scale a domain of categories and a range spanning the plot width. Give the inner x scale a domain of series names and a range spanning one outer band. The outer scale locates a category; the inner scale supplies the series offset within that category. The band scales’ bandwidths provide the dimensions for the bars.

Set the y scale’s domain to cover the values you intend to show and its range from the plot bottom to the top. A single shared y scale makes a direct visual comparison between series, so use it only when those series have comparable units.

Join values to rectangles

For each category, transform its named fields into series/value pairs, such as {key: "apples", value: 12}. Use an outer join to create or select a group for each category, then an inner join inside each group to create or select one rectangle per series. Set each rectangle’s horizontal position to the category’s outer position plus the series’ inner position. Set its vertical position from the y scale, and its height to the distance between the y-scaled value and the plot bottom.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

This nested selection pattern follows D3’s documented approach for joining matrix-like data. The getting-started guide also demonstrates the margin convention: define the inner plot area, map scale ranges to it, then place the x axis at the bottom and the y axis at the left.

Add axes and make the chart readable

Generate the category axis from the outer band scale and place it along the plot bottom. Generate the value axis from the y scale and place it on the left. Add a legend or direct labels to identify series; label the units as well. Choose colors with enough contrast to distinguish the series, but do not rely on color alone when labels can make the mapping clearer.

When the input changes, recalculate the relevant scale domains and call the axis generators again so the axes match the updated chart.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Choose grouped bars, stacked bars, or small multiples

Layout Best for Trade-off
Grouped bars Comparing individual series values within each category Each category uses horizontal space for every series, so many categories or series can make bars and labels cramped.
Stacked bars Comparing category totals and showing each series’ contribution to a whole Interior segments do not share a common baseline, making their values harder to compare directly.
Small multiples Inspecting series separately, especially when their units differ Each measure occupies its own panel, so cross-panel comparison depends on consistent design and scales.

These are chart-design choices, not D3 API requirements. If series have incompatible units or values so far apart that a shared scale obscures smaller ones, small multiples or another display can be more honest than a shared axis. For bars intended to compare magnitude directly, a shared linear scale communicates that the values are comparable.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.