
How to Make a Pie Chart in Confluence, Plus Bar and Line Charts
Short answer: to make a pie chart in Confluence Cloud, add a two-column table (labels and numbers), click it in edit mode, choose Insert chart in the table toolbar and pick Pie. The chart sits below the table and updates when the numbers change. No app is needed.
That covers most pie charts. This guide also shows how to put percentages on the slices with the Chart macro, how to chart Jira issues with the Jira Chart macro, and how to build interactive pie, doughnut, bar and line charts with Chart.js inside HTML Macro+ for Confluence when the built-in options aren't enough. Confluence calls all of these charts; if you searched for a Confluence graph, it's the same thing.
How to make a pie chart in Confluence
A pie chart needs just two columns, one for the labels and one for the values:
| Request type | Tickets |
|---|---|
| Access | 42 |
| Bug | 31 |
| How-to | 18 |
| Other | 9 |
- In edit mode, add the table, or click one that's already on the page.
- In the table's floating toolbar, select Insert chart.
- Pick Pie.
- Set the category to the first column and the data series to the second, then adjust colours, height and legend.
- Publish.
The chart stays connected to the table, so when someone edits a number, the slice changes size. If readers only need the chart, put the table inside an Expand macro so it's collapsed by default.
Keep a pie to five or six slices. Past that, the small slices are hard to tell apart, and a bar chart reads better. Group the long tail into an "Other" row, as in the table above.
Show percentages on the slices
The Insert chart pie is flat and has few styling options. The older Chart macro gives you more control over the labels:
- In edit mode, type
/chartand select Chart. - Set Type to pie and add a Title.
- Click into the macro body and add the two-column table.
- Set Pie Section Label to
%0% (%2%)to show each label with its percentage, or%0% = %1%to show the value.%0%is the label,%1%the number and%2%the percentage. - Publish. The table is hidden and the pie shows in its place.
To pull one slice out of the pie, list its label in Pie Section Explode. The options are in Atlassian's Chart macro reference.
Make a pie chart of Jira issues
If the numbers come from Jira, don't copy them into a table. Confluence has a built-in Jira Chart macro that draws a pie chart straight from a Jira search:
- In edit mode, type
/jiraand select Jira Chart. - Choose Pie chart and enter a Jira search in JQL, such as
project = SUP AND status != Done. - Under Display options, set Chart by to the field to split on: status, priority, assignee, issue type, component or fix version.
- Insert the macro and publish.
The chart refreshes from Jira, so it stays current without anyone editing the page. See Atlassian's Jira Chart macro docs for the other chart types. For charts on a Jira dashboard rather than a Confluence page, see how to track Jira issues with charts.
Make a bar or line chart from a table
The same two built-in tools draw other chart types. The first row of the table holds the headers, the first column holds the labels, and the other cells hold numbers. This table gives you a two-series bar chart:
| Sprint | Bugs opened | Bugs closed |
|---|---|---|
| Sprint 21 | 14 | 9 |
| Sprint 22 | 11 | 13 |
| Sprint 23 | 8 | 12 |
Option 1: Insert chart
- In edit mode, click anywhere in the table.
- In the table's floating toolbar, select Insert chart. The chart appears below the table.
- Pick Bar, Line or Pie, then set the X-axis (or category for a pie), the data series, colours, height and legend.
- Publish.
Option 2: The Chart macro
The Chart macro is older but supports more types: area, scatter, time series and Gantt as well as bar, line and pie.
- In edit mode, type
/chartand select Chart. - Set Type, a Title and Show legend.
- Click into the macro body and add your table.
- Set Content orientation: vertical when each column is a data series, horizontal when each row is one.
- Publish. The table is hidden and the chart shows in its place.
Two things trip people up. Don't leave a cell empty: Atlassian's docs say to enter 0 instead, because a blank cell can stop the chart rendering. And the default size is 300 by 300 pixels, which looks small on a wide page, so set Width to 600 or more.
Built-in charts or HTML Macro+?
| Insert chart | Chart macro | Jira Chart macro | HTML Macro+ with Chart.js | |
|---|---|---|---|---|
| Install needed | No | No | No | Yes, free for up to 10 users |
| Data | Table on the page, stays connected | Table inside the macro | A Jira search | Data in the code, or fetched from an API |
| Chart types | Bar, line, pie | Bar, line, pie, area, scatter, time series, Gantt | Pie, created vs resolved, two-dimensional | Anything Chart.js draws, including doughnut, radar and mixed charts |
| Percentages on a pie | No | Yes, with Pie Section Label | No | Yes, in labels or tooltips |
| Hover tooltips and toggling series | Basic | No | No | Yes |
| Styling | Colours, height, legend | Size, legend, orientation | Width, border | Full control with CSS and Chart.js options |
| Best for | Quick charts that track a table | Labelled pies and extra chart types | Live counts of Jira issues | Dashboards and charts that need to look exactly right |
Start with Insert chart. Move to HTML Macro+ when you hit its limits. People also search for "Chart from Table": that's a macro in Stiltsoft's Table Filter, Charts & Spreadsheets app on the Marketplace, not a built-in Confluence feature.
Interactive charts with HTML Macro+: before you start
1. Install the app. Install HTML Macro+ for Confluence from the Atlassian Marketplace. It runs on Atlassian Forge and is free for sites with up to 10 users; larger sites get a free 1-month trial. Until 28 February 2027, there's 25% off monthly and annual subscriptions: request the code.
2. Allow the CDN. The examples load Chart.js from cdn.jsdelivr.net, so a Confluence admin needs to allow that domain:
- Go to Confluence Administration → Manage Apps.
- Find HTML Macro+ for Confluence and click Configure.
- On the Security tab, choose Whitelist only mode (if it isn't already selected).
- Add
cdn.jsdelivr.net(just the domain, nohttps://). You can type it and press Enter, or use the quick-add button for jsDelivr. - Click Save Changes.
See security settings for the other modes and domain formats.
3. Insert the macro. Edit a page, type /html and select HTML Macro+ for Confluence. The editor has three tabs: HTML, CSS and JavaScript. In each example below, the canvas goes in the HTML tab and the chart code goes in the JavaScript tab. Use the live preview to check the chart before you save.
Load Chart.js once per macro
Start the JavaScript tab with this helper. It loads a pinned version of Chart.js and runs your chart code once the library is ready:
function loadChartJs(callback) {
if (window.Chart) return callback();
const script = document.createElement('script');
script.src = 'https://cdn.jsdelivr.net/npm/[email protected]/dist/chart.umd.js';
script.onload = callback;
document.head.appendChild(script);
}
Pinning the version (@4.4.1) means a future Chart.js release can't change your charts unexpectedly. The examples below assume this helper is at the top of the JavaScript tab.
Bar chart: team metrics or sprint data
Good for comparing values across categories: issues by status, story points per sprint, bugs per team.
HTML
<canvas id="barChart" width="700" height="350"></canvas>
JavaScript (after the helper)
loadChartJs(() => {
new Chart(document.getElementById('barChart'), {
type: 'bar',
data: {
labels: ['To Do', 'In Progress', 'In Review', 'Done'],
datasets: [{
label: 'Issues',
data: [12, 8, 5, 34],
backgroundColor: ['#94a3b8', '#3b82f6', '#f59e0b', '#22c55e'],
borderRadius: 6,
}]
},
options: {
responsive: false,
plugins: {
legend: { display: false },
title: {
display: true,
text: 'Issue Status, Sprint 42',
font: { size: 15, weight: '600' },
color: '#1e293b',
}
},
scales: {
y: { beginAtZero: true, grid: { color: '#f1f5f9' }, ticks: { color: '#64748b' } },
x: { grid: { display: false }, ticks: { color: '#64748b' } }
}
}
});
});
Replace the labels and data arrays with your own values. Each label maps to the data value at the same position.
Line chart: velocity trend or weekly progress
Good for trends over time: sprint velocity, bug discovery rate, weekly active users.
HTML
<canvas id="lineChart" width="700" height="350"></canvas>
JavaScript
loadChartJs(() => {
new Chart(document.getElementById('lineChart'), {
type: 'line',
data: {
labels: ['Sprint 37', 'Sprint 38', 'Sprint 39', 'Sprint 40', 'Sprint 41', 'Sprint 42'],
datasets: [{
label: 'Story Points Completed',
data: [41, 38, 45, 52, 49, 55],
borderColor: '#6366f1',
backgroundColor: 'rgba(99, 102, 241, 0.08)',
borderWidth: 2,
pointBackgroundColor: '#6366f1',
pointRadius: 4,
fill: true,
tension: 0.3,
}]
},
options: {
responsive: false,
plugins: {
legend: { position: 'top' },
title: {
display: true,
text: 'Sprint Velocity, Last 6 Sprints',
font: { size: 15, weight: '600' },
color: '#1e293b',
}
},
scales: {
y: { beginAtZero: false, grid: { color: '#f1f5f9' }, ticks: { color: '#64748b' } },
x: { grid: { display: false }, ticks: { color: '#64748b' } }
}
}
});
});
Chart.js pie chart with percentages
Good for showing how a total is split: issue types, budget allocation, time by category. Unlike the built-in pie, hovering a slice shows its share of the total. Keep it to five or six slices.
HTML
<canvas id="pieChart" width="500" height="400"></canvas>
JavaScript
loadChartJs(() => {
new Chart(document.getElementById('pieChart'), {
type: 'pie',
data: {
labels: ['Bug', 'Feature', 'Task', 'Tech Debt', 'Spike'],
datasets: [{
data: [18, 32, 25, 14, 11],
backgroundColor: ['#ef4444', '#6366f1', '#3b82f6', '#f59e0b', '#94a3b8'],
borderWidth: 2,
borderColor: '#fff',
}]
},
options: {
responsive: false,
plugins: {
legend: { position: 'right' },
title: {
display: true,
text: 'Open Issues by Type',
font: { size: 15, weight: '600' },
color: '#1e293b',
},
tooltip: {
callbacks: {
label: (ctx) => {
const total = ctx.dataset.data.reduce((sum, value) => sum + value, 0);
const percent = Math.round((ctx.parsed / total) * 100);
return `${ctx.label}: ${ctx.parsed} (${percent}%)`;
}
}
}
}
}
});
});
The tooltip callback adds up the slices and shows each one as a number and a percentage, for example "Feature: 32 (32%)". To turn the pie into a doughnut, change type: 'pie' to type: 'doughnut'.
Chart.js doughnut chart: goal progress or completion
Good for a single metric against a target: sprint completion, budget consumed, onboarding progress.
HTML
<div class="donut">
<canvas id="doughnutChart" width="400" height="400"></canvas>
<div class="donut-label">
<div class="donut-value">72%</div>
<div class="donut-caption">Complete</div>
</div>
</div>
CSS
.donut { position: relative; width: 400px; margin: 0 auto; }
.donut-label {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
font-family: sans-serif;
}
.donut-value { font-size: 36px; font-weight: 700; color: #1e293b; }
.donut-caption { font-size: 13px; color: #64748b; }
JavaScript
loadChartJs(() => {
new Chart(document.getElementById('doughnutChart'), {
type: 'doughnut',
data: {
datasets: [{
data: [72, 28],
backgroundColor: ['#6366f1', '#f1f5f9'],
borderWidth: 0,
}]
},
options: {
responsive: false,
cutout: '78%',
plugins: {
legend: { display: false },
tooltip: { enabled: false },
}
}
});
});
Change 72 and 28 (they should add up to 100) and update the center label to match.
Multi-series line chart: compare two teams or products
When you want two data series on the same time axis:
HTML
<canvas id="multiLineChart" width="700" height="350"></canvas>
JavaScript
loadChartJs(() => {
new Chart(document.getElementById('multiLineChart'), {
type: 'line',
data: {
labels: ['Week 1', 'Week 2', 'Week 3', 'Week 4', 'Week 5', 'Week 6'],
datasets: [
{
label: 'Team Alpha',
data: [12, 19, 15, 22, 18, 25],
borderColor: '#6366f1',
backgroundColor: 'transparent',
borderWidth: 2,
pointRadius: 4,
tension: 0.3,
},
{
label: 'Team Beta',
data: [8, 14, 20, 17, 24, 21],
borderColor: '#22c55e',
backgroundColor: 'transparent',
borderWidth: 2,
pointRadius: 4,
tension: 0.3,
}
]
},
options: {
responsive: false,
plugins: {
legend: { position: 'top' },
title: {
display: true,
text: 'Weekly Issues Resolved',
font: { size: 15, weight: '600' },
color: '#1e293b',
}
},
scales: {
y: { beginAtZero: true, grid: { color: '#f1f5f9' } },
x: { grid: { display: false } }
}
}
});
});
Tips for production use
Decide where the data comes from. The simplest option is to keep the arrays in the code and treat the page as a snapshot: update the numbers when you update the commentary. JavaScript's fetch() also works inside the macro, as long as the API's domain is on the whitelist and the API allows cross-origin requests from the browser. Don't put API tokens or passwords in macro code, because the code runs in every viewer's browser.
Give the canvas a size. The macro adjusts its height to fit the content automatically, so a canvas with width and height attributes and responsive: false gives predictable results. If you'd rather have the chart fill the available width, set responsive: true and leave Chart.js's default aspect ratio on so the height follows the width.
Give each chart a unique id. If one macro holds several charts, give each canvas a different id (barChart, lineChart and so on) and call loadChartJs for each.
Test in the live preview before saving. The preview runs the same code, under the same security settings, that page visitors get.
If the chart is blank
The most common cause is that cdn.jsdelivr.net isn't on the whitelist, or the site is in Block all mode. A blocked script doesn't draw anything, so check the browser console for a Content Security Policy error and confirm the domain in the app's security settings. If an admin has just changed the settings, click Refresh in the preview toolbar to reload them. The troubleshooting guide covers other causes.
If your site blocks all external CDNs, you can paste the minified Chart.js source into the JavaScript tab instead of loading it. The minified bundle is roughly 200 KB, well within the default 2 MB content size limit, but it does make the macro heavier to edit.
FAQ
Can Confluence make a chart from a table?
Yes. Click the table in edit mode and choose Insert chart in the floating toolbar. Confluence adds a bar, line or pie chart below the table and keeps it in sync with the table's numbers.
How do I make a pie chart in Confluence?
Make a two-column table with labels and values, click it, choose Insert chart and pick Pie. For a doughnut, custom colours or percentage tooltips, use Chart.js in HTML Macro+.
How do I show percentages on a Confluence pie chart?
Use the Chart macro with Type set to pie and Pie Section Label set to %0% (%2%). Each slice is then labelled with its name and percentage. The Insert chart pie doesn't show percentages.
Can I make a pie chart of Jira issues in Confluence?
Yes. The built-in Jira Chart macro draws a pie chart from a Jira search and splits it by a field such as status, priority or assignee. It updates from Jira, so there's no table to maintain.
How do I make a graph in Confluence?
Confluence calls graphs charts. Put the numbers in a table, click it and choose Insert chart for a bar, line or pie chart, or use the Chart macro for area, scatter and time series graphs.
Why is my Confluence chart blank?
With the Chart macro it's usually an empty cell or text in a number column, so enter 0 for missing values. With Chart.js in HTML Macro+, check that cdn.jsdelivr.net is on the app's whitelist.
Is "Chart from Table" a built-in Confluence macro?
No. Chart from Table comes from Stiltsoft's Table Filter, Charts & Spreadsheets app. The built-in options are Insert chart and the Chart macro.
More ideas
- 5 things you can build with HTML Macro+: status badges, decision trees, sortable tables
- How to build a custom status dashboard in Confluence
- 5 ways to use HTML in Confluence Cloud
- How to track Jira issues with charts, for charts on a Jira dashboard
Install HTML Macro+ for Confluence from the Atlassian Marketplace


