How do I create a 100% stacked horizontal bar chart?

I’ve been struggling to create a 100% stacked horizontal bar graph like the one below. Any help would be much appreciated.
image

  <canvas id="myChart" width=50 height=10></canvas>
  <script>
chart = new Chart(document.getElementById("myChart"), {
  type: "bar",
  data: {
    labels: ["Label 1", "Label 2"],
    datasets: [
      { label: "Failed", data: [1, 0], backgroundColor: "rgba(253, 90, 62, 1.0)" },
      { label: "Broken", data: [1, 0], backgroundColor: "rgba(255, 208, 80, 1.0)" },
      { label: "Passed", data: [1, 1], backgroundColor: "rgba(151, 204, 100, 1.0)" },
    ],

  },
  options: {
    indexAxis: "y",
    plugins: {
      stacked100: { enable: true },
    },
  },
});

var image = chart.toBase64Image();
console.log(image);
<script>

Using stacked100 chartjs plugin I could make this. Its not perfect, but I’m getting there

Hi @mplnv, the approach for 100% horizontal bar charts is a bit strange without the plugin, but it’s certainly doable. The key is to use a horizontalBar and set arrays of backgroundColors. I put this together before your followup post but it should help a bit. Let me know if you have followup questions.

Here’s the example with Chart.js v2:

Link to editor

{
  type: 'horizontalBar',
  data: {
    labels: ['Label 1', 'Label 2'],
    datasets: [
      {
        backgroundColor: ['#fd5a3e', null],
        data: [0.5, null],
        barThickness: 30,
      },
      {
        backgroundColor: ['#ffd050', '#97cc64'],
        data: [0.5, 1.0],
        barThickness: 30,
      },
    ],
  },
  options: {
    legend: {
      position: 'bottom',
      labels: {
        generateLabels: (chart) => [
          {
            text: 'Failed',
            fillStyle: '#fd5a3e',
          },
          {
            text: 'Broken',
            fillStyle: '#ffd050',
          },
          {
            text: 'Passed',
            fillStyle: '#97cc64',
          },
        ],
      },
    },
    scales: {
      xAxes: [
        {
          stacked: true,
          ticks: { min: 0, max: 1, display: false },
          gridLines: { display: false },
        },
      ],
      yAxes: [{ stacked: true, gridLines: { drawBorder: false } }],
    },
    plugins: {
      datalabels: {
        display: true,
        color: '#fff',
        font: {
          style: 'bold',
        },
        formatter: () => {
          return '1';
        },
      },
    },
  },
};

@ian thank you very much. Initially I was trying it with v2 only but I couldn’t do it without the plugins. Yes the approach is a bit strange, when the numbers change the data has to be sliced and fed to the graph. Anyway I thought it was impossible to do but you proved me wrong. Thank you very much for the help.

This is the chart I created with Charts v3.
image

And here’s the code.

<script src=https://cdn.jsdelivr.net/npm/chart.js@3.0.0/dist/chart.min.js></script>
<script src=https://cdn.jsdelivr.net/npm/chartjs-plugin-stacked100@1.0.0></script>
<script src=https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@2.0.0></script>
<canvas id="myChart" style="position: relative; height:150; width:500"></canvas>
<script>
Chart.register(ChartjsPluginStacked100.default);
Chart.register(ChartDataLabels);
const chart = new Chart(document.getElementById("myChart").getContext("2d"), {
	type: "bar",
	data: {
		labels: ["Label 1", "Label 2"],
		datasets: [ 
			{ label: "Failed", data: [2, 0], backgroundColor: "rgba(253, 90, 62, 1.0)" },
			{ label: "Broken", data: [1, 0], backgroundColor: "rgba(255, 208, 80, 1.0)" },
			{ label: "Passed", data: [0, 125], backgroundColor: "rgba(151, 204, 100, 1.0)" }]
	},
	options: {
		scales: {
			x: { display: false },
			y: { grid: { drawBorder: false }}
		},
		maintainAspectRatio: false,
		responsive: false,
		indexAxis: "y",
		plugins: {
			stacked100: { enable: true },
			datalabels: {
				anchor: 'center',
				align: 'center',
				formatter: (_value, context) => {
					const {
						datasetIndex, dataIndex
					} = context;
					const rawValue = context.chart.data.originalData[datasetIndex][dataIndex];
					return rawValue || "";
				},
				color: '#FFFFFF',
				font: {
					weight: 'bold'
				},
			},
			legend: {
				display: true,
				position: 'bottom',
			},
		},
	},
});
var image = chart.toBase64Image();
console.log(image);
</script>

@ian But for some reason the base64 encoding is wrong. I’m unable to reproduce the image :cold_sweat:

Do you have an example URL? I’d suggest URL encoding the chart config instead of base64 encoding it.