Add live data to a responsive stacked bar chart in Chart.js v4
Configure stacked scales, register v4 components, and push new data points without reloading the page.
23 Apr 2026, 20:25 UTC

Problem: stacked bars that resize and grow without a reload
You need a Chart.js bar chart where segments stack on a single column per category, the chart fills its container as the window changes, and new categories or values can be added after the page loads. A full page reload defeats the purpose of a live dashboard, and Chart.js v4 requires explicit component registration when you import it as an ES module.
Takeaway: set stacked: true on both the X and Y scales, keep responsive: true with maintainAspectRatio: false, push matching values into every dataset and the shared label array, then call chart.update().
Prerequisites
- Chart.js v4 installed from npm or loaded from a CDN that serves the v4.x series.
- A modern browser with JavaScript enabled.
- Basic familiarity with HTML canvas and ES module imports.
1. Create the container and canvas
Chart.js draws on a <canvas> element, which is a bitmap surface for scripted graphics. The container must have an explicit width or live inside a flex or grid layout; otherwise a responsive chart can collapse to zero height.
<div style='width: 700px; height: 400px;'>
<canvas id='stackedBar'></canvas>
</div>
<button id='addPoint'>Add data point</button>
The inline dimensions give the chart a starting size. Because maintainAspectRatio will be false, the canvas stretches to fill that container.
2. Import and register Chart.js v4 components
In v4, scales, elements, and plugins are not loaded automatically in module builds. Register the pieces you need before creating the chart.
import { Chart, CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend } from 'chart.js';
Chart.register(
CategoryScale,
LinearScale,
BarElement,
Title,
Tooltip,
Legend
);
If you load Chart.js from a global CDN script instead, skip the import and registration step, but confirm the URL points to v4.x; v2 and v3 options will not work with this pattern.
3. Initialize the stacked bar chart
Get the 2D rendering context from the canvas, then create the chart. Both axis scales must declare stacked: true so segments combine into one bar per label instead of side-by-side bars.
const ctx = document.getElementById('stackedBar').getContext('2d');
const chart = new Chart(ctx, {
type: 'bar',
data: {
labels: ['Jan', 'Feb', 'Mar'],
datasets: [
{
label: 'Apples',
data: [10, 12, 8],
backgroundColor: '#4e79a7'
},
{
label: 'Oranges',
data: [5, 7, 6],
backgroundColor: '#f28e2b'
}
]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
x: { stacked: true },
y: { stacked: true }
},
animation: {
duration: 0
}
}
});
Setting animation.duration to zero removes the draw animation on updates, which keeps the interface responsive when points are added frequently.
4. Add new data points dynamically
To add a category, push a label into chart.data.labels and push one value into the data array of every dataset. All datasets must share the same label count; mismatched lengths misalign the stack and can produce blank or shifted segments.
const button = document.getElementById('addPoint');
const months = ['Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep'];
button.addEventListener('click', () => {
const nextLabel = months.shift();
if (!nextLabel) return;
chart.data.labels.push(nextLabel);
chart.data.datasets.forEach((dataset) => {
dataset.data.push(Math.floor(Math.random() * 10) + 1);
});
chart.update();
});
Call chart.update() once after all arrays are changed. Repeated updates inside a loop force a full re-render each time and can freeze the UI on large datasets. If you are adding many points, collect them first and update once, or throttle the user action to no more than a few times per second.
5. Verify the result
- Resize the browser window. The canvas should fill its container while the bars remain stacked.
- Click the add-point button. A new stacked bar should appear without a page reload.
- Open the browser console. There should be no Chart.js errors after
chart.update(). - Hover over a segment. The tooltip should show the segment value; the stacked total appears automatically for the bar.
- Use the browser performance panel to time
chart.update(). For up to 1,000 points it should complete well under 100 ms; if it is slower, reduce update frequency or decimate the data.
Recovery and cleanup
If you recreate the chart—for example, when a route changes in a single-page application—destroy the previous instance first. This removes event listeners and detaches the canvas, preventing memory leaks.
chart.destroy();
const chart = new Chart(ctx, { ... });
If the chart does not render, check that every dataset's data array has the same length as chart.data.labels, and confirm the container has a non-zero width and height.
Limitations
- Chart.js redraws the whole chart on
update(); it does not patch only the new bar. - Stacked mode requires identical label arrays across all datasets.
- Responsiveness depends on the parent container; Chart.js cannot size itself if the parent has no dimensions.
- Frequent updates without throttling can block the main thread.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.