Learn to output JSON from Collection Lists, feed it into Chart.js, and style accessible, performant charts that auto-update when editors change CMS items.
Published July 2025 • 10 min read
SaaS dashboards, annual reports and fintech landing pages scream for data visualisation, but screenshots of Excel feel 2010. Until 2024 most Webflow users embedded Google Sheets charts (slow) or Iframes from Tableau (heavy). Thanks to inline <canvas>
support and the lightweight Chart.js 4, you can render crisp, responsive graphs that update whenever editors tweak CMS items—no code export or rebuild required.
Create a collection called Metrics with fields:
Name
(Plain text: e.g. Monthly Revenue)Labels
(Rich text or Plain text, comma-separated months)Data Points
(Plain text: comma list 12000,14500,16000…)Colour
(Color)One item = one dataset in Chart.js. Editors can add new items without touching code.
<div id="chartData" style="display:none">
<div class="metric-item" fs-cmsitem="">
<span class="metric-labels">{{labels}}</span>
<span class="metric-data">{{data-points}}</span>
<span class="metric-colour" style="background:{{colour}}"></span>
</div>
</div>
Webflow will repeat .metric-item
for each CMS row on publish.
Place a <canvas id="myChart" width="800" height="400"></canvas>
where you want the graph. Give the wrapper position:relative
and set canvas to width:100%
for responsiveness.
Add to Site Settings → Custom Code → <head>:
<script type="module">
import { Chart, BarController, BarElement, CategoryScale, LinearScale, Tooltip } from 'https://cdn.jsdelivr.net/npm/chart.js@4.5.1/+esm';
Chart.register(BarController, BarElement, CategoryScale, LinearScale, Tooltip);
window.Chart = Chart;
</script>
Only 14 kB after gzip—much lighter than full bundle.
<script>
const items = [...document.querySelectorAll('.metric-item')].map(el => ({
labels: el.querySelector('.metric-labels').textContent.split(','),
data: el.querySelector('.metric-data').textContent.split(',').map(Number),
colour: getComputedStyle(el.querySelector('.metric-colour')).backgroundColor
}));
const datasets = items.map(i => ({
label: i.label || 'Dataset',
data: i.data,
backgroundColor: i.colour
}));
new Chart(document.getElementById('myChart'), {
type: 'bar',
data: { labels: items[0].labels, datasets },
options: { responsive:true, plugins:{ tooltip:{ callbacks:{ label:ctx => `$${ctx.parsed.y.toLocaleString()}` } } } }
});
</script>
The script reads hidden DOM nodes, so editors can change numbers in the Webflow Editor and republish—chart updates instantly.
Chart.js respects CSS variables. Tie backgroundColor
to your --primary-500
Variable or switch palettes on [data-theme='dark']
attribute for seamless dark-mode support.
role="img" aria-label="Bar chart of monthly revenue"
to the canvas.requestIdleCallback
.#myChart
.Need real-time data? Use Webflow’s CMS Webhooks (Item Updated) → Netlify Function → Pusher / Socket.io to push new JSON to the page and call chart.update()
—no refresh required.
With a few lines of ES modules and clever CMS markup, Webflow can power fully-dynamic, responsive charts—perfect for SaaS metrics, startup pitch decks or interactive landing pages. No React, no heavy libs; just native Chart.js and the CMS you already love.
Lorem ipsum dolor sit amet consectetur mi urna tellus dignissim duis at in tempor mauris morbi fermentum dolor lobortis aliquam maecenas.