Stacked Columns and Bars in JavaScript

Using ApexCharts with JavaScript

This Stacked Columns and Bars example uses ApexCharts.js directly in JavaScript, with no wrapper component.

Install it with npm install apexcharts, then mount the chart with new ApexCharts(element, options).render().

JavaScript installation guide
// Shared by the vanilla-js, React and Vue builds.
//
// Website sessions (thousands) per month by device (the wholes), and what
// each traffic source brought in on that device (the parts). Picking a source
// keeps every device on both charts: the stacks are drawn faded at their full
// size, with the source's own stack solid in front, from the same baseline.
var MONTHS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun']
var DEVICES = ['Desktop', 'Mobile']
var SESSIONS = [
  [42, 45, 48, 44, 50, 53],
  [58, 62, 66, 71, 75, 80],
]
var SOURCES = {
  search: [
    [20, 22, 23, 21, 24, 25],
    [24, 26, 28, 30, 31, 33],
  ],
  social: [
    [8, 9, 10, 9, 11, 12],
    [22, 24, 26, 29, 31, 34],
  ],
  email: [
    [9, 9, 10, 9, 10, 11],
    [7, 7, 8, 8, 9, 9],
  ],
}

function seriesFor(source) {
  return DEVICES.map(function (name, i) {
    var s = { name: name, data: SESSIONS[i] }
    if (source) s.highlightData = SOURCES[source][i]
    return s
  })
}

// One call per chart and pick: the parts go in, each chart animates from what
// is on screen. Clearing is the same call without them.
function pickSource(source) {
  document.querySelectorAll('[data-source]').forEach(function (b) {
    b.classList.toggle('active', b.getAttribute('data-source') === source)
  })
  return Promise.all(
    ['sessions', 'shares'].map(function (id) {
      return ApexCharts.getChartByID(id).updateSeries(seriesFor(source))
    }),
  )
}

function wireSources() {
  document.querySelectorAll('[data-source]').forEach(function (b) {
    b.addEventListener('click', function () {
      pickSource(b.getAttribute('data-source'))
    })
  })
}

var options = {
  series: seriesFor('search'),
  chart: {
    id: 'sessions',
    type: 'bar',
    height: 360,
    stacked: true,
    toolbar: { show: false },
  },
  colors: ['#2563eb', '#16a34a'],
  plotOptions: {
    bar: {
      columnWidth: '56%',
      borderRadius: 4,
      borderRadiusWhenStacked: 'last',
      dataLabels: { total: { enabled: true, style: { fontSize: '12px' } } },
    },
  },
  dataLabels: { enabled: false },
  stroke: { show: true, width: 1, colors: ['#fff'] },
  xaxis: { categories: MONTHS },
  yaxis: { title: { text: 'Sessions (thousands)' } },
  legend: { position: 'bottom' },
  tooltip: { shared: true, intersect: false },
}

var chart = new ApexCharts(document.querySelector('#chart'), options)
chart.render()

var options1 = {
  series: seriesFor('search'),
  chart: {
    id: 'shares',
    type: 'bar',
    height: 280,
    stacked: true,
    stackType: '100%',
    toolbar: { show: false },
  },
  colors: ['#2563eb', '#16a34a'],
  plotOptions: {
    bar: { horizontal: true, barHeight: '64%' },
  },
  dataLabels: { enabled: true, style: { fontSize: '11px' } },
  stroke: { show: true, width: 1, colors: ['#fff'] },
  xaxis: { categories: MONTHS },
  legend: { show: false },
  tooltip: { shared: true, intersect: false },
}

var chart1 = new ApexCharts(document.querySelector('#chart2'), options1)
chart1.render()

wireSources()