Skip to content Skip to sidebar Skip to footer

Chart.js Legend Took Up Too Much Spaces

I was having some problem with chart.js legend. The legend with long text took up too much spaces which resulting in the reduce in the size of my pie chart: Another example is this

Solution 1:

First off, set canvas­'s width and height using it­'s native attributes (do not use style attribute), like so :

<canvas id="brandChart" width="700" height="350"></canvas>

Then, set responsive property to false in your chart options, as such :

options: {
   responsive:false,
   ...
}

ᴅᴇᴍᴏ

var chart = newChart(brandChart, {
   type: 'doughnut',
   data: {
      labels: ['Etronin Home Appliances Service & trading Pte Ltd', 'Giant'],
      datasets: [{
         data: [30, 70],
         backgroundColor: ['#2196f3', '#4caf50']
      }]
   },
   options: {
      responsive: false,
      legend: {
         display: true,
         position: 'right',
         onClick: null
      },
   }
});
<scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.min.js"></script><canvasid="brandChart"width="700"height="350"></canvas>

Solution 2:

Long legend nowrap is a known issue check https://github.com/chartjs/Chart.js/issues/3641

May be they can cover it in next releases. For now the solution is to remove the native legend and draw your custom one

I've created this plunk as an example for doghnut chart with custom legend https://embed.plnkr.co/5nuGS2KEV6hvESwGrOse/

Solution 3:

I bumped into a similar issue while using a bar chart with several items in legend positioned at the bottom, I set responsive:true

options: {
    responsive:true,
    legend: {
      display:true,
      position:"bottom",
      labels: {
        fontColor:"#3f5761"
      }
    },
    scales: {
      yAxes: [
        {
          ticks: {
            beginAtZero:true
          },
          scaleLabel: {
            display:true,
            labelString:"No. of tasks",
            fontSize:10
          }
        }
      ]
    }
  }

and set the height to the canvas as I wanted the width to be responsive. It looks better now.

<canvas #taskCountsChartheight="350"></canvas>

Solution 4:

There's no option that can be defined to easily achieve what you're looking for. An open feature request exists for such an option since 2016.

You'll have to generate custom HTML legend using legendCallback together with some CSS. The following code expects multi-line labels to be defined as arrays inside data.labels. It is aimed to be used for charts that have a unique dataset and where each legend label represents a value of its data (In case you need a solution for a chart with multiple datasets, please take a look at this answer).

legendCallback: chart => {
  let html = '<ul>';
  chart.data.labels.forEach((l, i) => {
    const ds = chart.data.datasets[0];
    const bgColor = ds.backgroundColor[i];
    const border = ds.borderWidth + 'px solid ' + ds.borderColor[i];
    html += '<li>' +
      '<span style="width: 36px; height: 14px; background-color:' + bgColor + '; border:' + border + '" onclick="onLegendClicked(event, \'' + i + '\')">&nbsp;</span>' +
      '<span id="legend-label-' + i + '" onclick="onLegendClicked(event, \'' + i + '\')">' +
      (Array.isArray(l) ? l.join('<br/>') : l) + '</span>' +
      '</li>';
  });
  return html + '</ul>';
}

To make this behave the same as standard Chart.js charts, the function onLegendClicked is invoked when a mouse click occurs on a legend label. This function toggles the hidden state of individual doughnut slices and changes label text style between normal and strike-through.

functiononLegendClicked(e, i) {
  let hidden = !chart.getDatasetMeta(0).data[i].hidden;
  chart.getDatasetMeta(0).data[i].hidden = hidden;
  const legendLabelSpan = document.getElementById("legend-label-" + i);
  legendLabelSpan.style.textDecoration = hidden ? 'line-through' : '';
  chart.update();
};

Please take a look at the executable code below and see how it works in action:

functiononLegendClicked(e, i) {
  let hidden = !chart.getDatasetMeta(0).data[i].hidden;
  chart.getDatasetMeta(0).data[i].hidden = hidden;
  const legendLabelSpan = document.getElementById("legend-label-" + i);
  legendLabelSpan.style.textDecoration = hidden ? 'line-through' : '';
  chart.update();
};

const chart = newChart('chart', {
  type: 'doughnut',
  data: {
    labels: [
      ['Label on', 'two lines'],     
      ['Legend label', 'spread over', 'three lines'],
       'A short label'
    ],
    datasets: [{
      data: [4, 5, 3],
      backgroundColor: ['rgba(255, 99, 132, 0.2)', 'rgba(255, 159, 64, 0.2)', 'rgba(54, 162, 235, 0.2)'],
      borderColor: ['rgb(255, 99, 132)', 'rgb(255, 159, 64)', 'rgb(54, 162, 235)'],
      borderWidth: 1
    }]
  },
  options: {
    legend: {
      display: false
    },
    tooltips: {
      callbacks: {
        title: (tooltipItems, data) => data.labels[tooltipItems[0].index],
        label: (tooltipItems, data) =>'Count: ' + data.datasets[0].data[tooltipItems.index]
      }
    },
    legendCallback: chart => {      
      let html = '<ul>';
      chart.data.labels.forEach((l, i) => {
        const ds = chart.data.datasets[0];
        const bgColor = ds.backgroundColor[i];
        const border = ds.borderWidth + 'px solid ' + ds.borderColor[i];
        html += '<li>' +
        '<span style="width: 36px; height: 14px; background-color:' + bgColor + '; border:' + border + '" onclick="onLegendClicked(event, \'' + i + '\')">&nbsp;</span>' +
        '<span id="legend-label-' + i + '" onclick="onLegendClicked(event, \'' + i + '\')">' +
        (Array.isArray(l) ? l.join('<br/>') : l) +'</span>' +
        '</li>';
      });
      return html + '</ul>';
    }
  }
});
document.getElementById("legend").innerHTML = chart.generateLegend();
#legend>ul {
  display: flex;
  justify-content: center;
}

#legendli {
  cursor: pointer;
  margin: 10px10px;
  display: flex;
}

#legendlispan {
  padding-left: 8px;
  font-family: Arial, Helvetica, sans-serif;
  font-size: 12px;
}
<scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script><div><divid="legend"></div><canvasid="chart"height="90"></canvas></div>

Solution 5:

This post is 9 months old but for the ones who are looking for a solution, use the following and this will make the pie/doughnut bigger in mobile/responsive view

Chart.defaults.global.maintainAspectRatio = false;

Post a Comment for "Chart.js Legend Took Up Too Much Spaces"