✊🏿 Black Lives Matter. Please consider donating to Black Girls Code today.

Bullet Charts in JavaScript

How to make a D3.js-based bullet chart in javascript.


Building full-stack apps and dashboards with Plotly.js?
Increase development speed by 2x-10x with Dash. 🏃


New to Plotly?

Plotly is a free and open-source graphing library for JavaScript. We recommend you read our Getting Started guide for the latest installation or upgrade instructions, then move on to our Plotly Fundamentals tutorials or dive straight in to some Basic Charts tutorials.

Stephen Few's Bullet Chart was invented to replace dashboard gauges and meters, combining both types of charts into simple bar charts with qualitative bars (steps), quantitative bar (bar) and performance line (threshold); all into one simple layout. Steps typically are broken into several values, which are defined with an array. The bar represent the actual value that a particular variable reached, and the threshold usually indicate a goal point relative to the value achieved by the bar. See indicator page for more detail.

var data = [
  {
    type: "indicator",
    mode: "number+gauge+delta",
    gauge: { shape: "bullet" },
    delta: { reference: 300 },
    value: 220,
    domain: { x: [0, 1], y: [0, 1] },
    title: { text: "Profit" }
  }
];

var layout = { width: 600, height: 250 };
Plotly.newPlot('myDiv', data, layout);

Below is the same example using "steps" attribute, which is shown as shading, and "threshold" to determine boundaries that visually alert you if the value cross a defined threshold.

var data = [
  {
    type: "indicator",
    mode: "number+gauge+delta",
    value: 220,
    domain: { x: [0, 1], y: [0, 1] },
    title: { text: "<b>Profit</b>" },
    delta: { reference: 200 },
    gauge: {
      shape: "bullet",
      axis: { range: [null, 300] },
      threshold: {
        line: { color: "red", width: 2 },
        thickness: 0.75,
        value: 280
      },
      steps: [
        { range: [0, 150], color: "lightgray" },
        { range: [150, 250], color: "gray" }
      ]
    }
  }
];

var layout = { width: 600, height: 250 };
var config = { responsive: true };

Plotly.newPlot('myDiv', data, layout, config);

The following example shows how to customize your charts. For more information about all possible options check our reference page.

var data = [
  {
    type: "indicator",
    mode: "number+gauge+delta",
    value: 220,
    domain: { x: [0, 1], y: [0, 1] },
    delta: { reference: 280, position: "top" },
    title: {
      text:
        "<b>Profit</b><br><span style='color: gray; font-size:0.8em'>U.S. $</span>",
      font: { size: 14 }
    },
    gauge: {
      shape: "bullet",
      axis: { range: [null, 300] },
      threshold: {
        line: { color: "red", width: 2, gradient: { yanchor: "vertical" } },
        thickness: 0.75,
        value: 270
      },
      bgcolor: "white",
      steps: [{ range: [0, 150], color: "cyan" }],
      bar: { color: "darkblue" }
    }
  }
];

var layout = { width: 400, height: 230 };
var config = { responsive: true };

Plotly.newPlot('myDiv', data, layout, config);

Bullet charts can be stacked for comparing several values at once as illustrated below:

var data = [
  {
    type: "indicator",
    mode: "number+gauge+delta",
    value: 180,
    delta: { reference: 200 },
    domain: { x: [0.25, 1], y: [0.08, 0.25] },
    title: { text: "Revenue" },
    gauge: {
      shape: "bullet",
      axis: { range: [null, 300] },
      threshold: {
        line: { color: "black", width: 2 },
        thickness: 0.75,
        value: 170
      },
      steps: [
        { range: [0, 150], color: "gray" },
        {
          range: [150, 250],
          color: "lightgray"
        }
      ],
      bar: { color: "black" }
    }
  },
  {
    type: "indicator",
    mode: "number+gauge+delta",
    value: 35,
    delta: { reference: 200 },
    domain: { x: [0.25, 1], y: [0.4, 0.6] },
    title: { text: "Profit" },
    gauge: {
      shape: "bullet",
      axis: { range: [null, 100] },
      threshold: {
        line: { color: "black", width: 2 },
        thickness: 0.75,
        value: 50
      },
      steps: [
        { range: [0, 25], color: "gray" },
        { range: [25, 75], color: "lightgray" }
      ],
      bar: { color: "black" }
    }
  },
  {
    type: "indicator",
    mode: "number+gauge+delta",
    value: 220,
    delta: { reference: 200 },
    domain: { x: [0.25, 1], y: [0.7, 0.9] },
    title: { text: "Satisfaction" },
    gauge: {
      shape: "bullet",
      axis: { range: [null, 300] },
      threshold: {
        line: { color: "black", width: 2 },
        thickness: 0.75,
        value: 210
      },
      steps: [
        { range: [0, 150], color: "gray" },
        { range: [150, 250], color: "lightgray" }
      ],
      bar: { color: "black" }
    }
  }
];

var layout = {
  width: 600, height: 250,
  margin: { t: 10, r: 25, l: 25, b: 10 }
};
Plotly.newPlot('myDiv', data, layout);