Composition / Beginner
Donut Chart
Show parts of a whole as segments around a ring.
Interactive Chart Preview
JAVASCRIPTEdit the column names and values to update your chart. Changes stay in this page until you reload.
| Row# | Category | Number | Remove row |
|---|---|---|---|
| 1 | |||
| 2 | |||
| 3 | |||
| 4 | |||
| 5 |
Use different slice names and nonnegative values with a positive total. Percentages are calculated automatically.
Chart.js Code Example
JAVASCRIPTimport Chart from 'chart.js/auto';
// Illustrative data used by the live preview.
const chartData = {
"categoryLabel": "Device",
"labels": [
"Desktop",
"Mobile",
"Tablet",
"Smart TV",
"Other"
],
"datasets": [
{
"label": "Traffic Source",
"data": [
45,
35,
12,
5,
3
],
"backgroundColor": [
"#3b82f6",
"#10b981",
"#f59e0b",
"#ef4444",
"#8b5cf6"
],
"borderColor": [
"#2563eb",
"#059669",
"#d97706",
"#dc2626",
"#7c3aed"
],
"borderWidth": 2,
"hoverOffset": 4
}
]
};
function createConfig(chartData) {
let chartType = 'bar';
let options = {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: 'bottom',
},
tooltip: {
mode: 'index',
intersect: false,
},
},
};
chartType = 'doughnut';
options.plugins.tooltip = {
callbacks: {
label: function (context) {
const total = context.dataset.data.reduce((sum, value) => sum + value, 0);
const percent = total > 0 ? ((context.parsed / total) * 100).toFixed(1) : '0.0';
return `${context.label}: ${context.parsed} (${percent}%)`;
},
},
};
return { type: chartType, data: structuredClone(chartData), options };
}
const chart = new Chart(document.getElementById('myChart'), createConfig(chartData));Preview and code follow the same library selection.
Run This Example
Install the package below in a browser project such as Vite. Put the copied code in a client JavaScript module and add this container to the page before the module runs.
npm install chart.js@4.5.1<div style="height:320px"><canvas id="myChart"></canvas></div>The example includes its sample data. When removing the chart, destroy or dispose of its instance and disconnect any resize observer.
Reading This Example
The default Chart.js example shows illustrative device shares totaling 100%: Desktop 45, Mobile 35, Tablet 12, Smart TV 5, and Other 3. Desktop and Mobile together represent 80%. The five-category dataset differs from the four-category pie example.
All library tabs use these illustrative values. Rendering styles and library APIs differ, so use the table to compare exact numbers.
About this example & sample data
| Device | Share (%) |
|---|---|
| Desktop | 45 |
| Mobile | 35 |
| Tablet | 12 |
| Smart TV | 5 |
| Other | 3 |
READ THE CHART
Read a Share of the Total
A donut chart shows parts of one whole as arcs around a ring. Its open center can hold a useful total or label. It is suited to a small set of shares, especially when the broad composition matters more than small differences.
Use One Complete Whole
Use nonnegative values from the same population and period. Categories should not overlap. If some data is excluded, explain that choice so the total remains meaningful.
Make Labels Do the Work
Include names and percentages beside the chart or in a clear legend. A central total needs a unit or description. Keep the ring thickness consistent and avoid effects that change the apparent size of an arc.
Do Not Overstate Readability
The center hole does not make close values easy to compare. Small slices can still be difficult to distinguish. Avoid using several donut charts when a shared bar chart would make differences clearer.
Choose an Alternative
Use a bar chart for ranking or precise comparisons. Use a pie chart when a full disk suits the presentation. When composition changes over time, consider whether a stacked view would make the sequence clearer.