[Chartjs]-Chart.js legend took up too much spaces

12👍

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>

note: width should be twice the height

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

options: {
   responsive: false,
   ...
}

ᴅᴇᴍᴏ

var chart = new Chart(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
      },
   }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.min.js"></script>
<canvas id="brandChart" width="700" height="350"></canvas>

4👍

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/

2👍

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 #taskCountsChart height="350"></canvas>

2👍

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.

function onLegendClicked(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:

function onLegendClicked(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 = new Chart('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;
}

#legend li {
  cursor: pointer;
  margin: 10px 10px;
  display: flex;
}

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

0👍

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;

Leave a comment