So here’s the thing—I was knee-deep in redesigning my website last month, trying to make it more blog-focused, when I realized something was missing. Sure, I’d added a search bar and cleaned up the navigation, but my data visualizations? They were, honestly, pretty boring.
That’s when I stumbled across ApexCharts, and wow, what a game-changer. If you’ve been wrestling with static charts or wondering how to make your Astro site more interactive, you’re gonna love this.
Let’s Start with Something Cool
Before we get into the weeds, check this out—here’s what we’re building toward:
Pretty slick, right? This mixed chart combines columns, areas, and lines all in one visualization. Trust me, your users will be impressed.
Getting Your Hands Dirty
Alright, let’s talk setup. First things first—you’ll need to grab ApexCharts:
# I prefer npm, but use whatever floats your boat
npm install apexcharts @types/apexcharts
# Or if you're team Yarn
yarn add apexcharts @types/apexcharts
Now here’s where most tutorials get it wrong. They’ll show you one chart and call it a day. But what happens when you want multiple charts on the same page? Chaos, that’s what.
🚨 Learned This the Hard Way
Building the Chart Component That Actually Works
Here’s the component I’ve been using—it handles multiple charts, accessibility, and won’t break when you throw real data at it:
---
// ChartsComponent.astro
interface Props {
chart: string;
chartId: string;
title?: string;
description?: string;
}
const { chart, chartId, title, description } = Astro.props;
---
<div class="chart-container w-full h-[400px] p-4 bg-white rounded-lg shadow-md">
{title && <h2 id={`${chartId}-title`} class="text-lg font-semibold mb-2">{title}</h2>}
{description && <p id={`${chartId}-desc`} class="text-sm text-gray-600 mb-4">{description}</p>}
<div
id={chartId}
role="img"
aria-labelledby={title ? `${chartId}-title` : undefined}
aria-describedby={description ? `${chartId}-desc` : undefined}
></div>
</div>
<script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
<script is:inline define:vars={{ chartData: chart, chartId }}>
try {
const options = JSON.parse(chartData);
// Add some nice default animations and accessibility
options.chart = {
...options.chart,
animations: {
enabled: true,
easing: 'easeinout',
speed: 800,
animateGradually: {
enabled: true,
delay: 150
},
dynamicAnimation: {
enabled: true,
speed: 350
}
},
accessibility: {
enabled: true,
announceNewData: {
enabled: true,
announcementPolicy: 'all'
}
}
};
document.addEventListener('DOMContentLoaded', function() {
const chart = new ApexCharts(document.querySelector(`#${chartId}`), options);
chart.render().catch(console.error);
});
} catch (error) {
console.error('Error rendering chart:', error);
document.querySelector(`#${chartId}`)?.insertAdjacentHTML(
'beforeend',
'<div class="text-red-500">Error rendering chart. Please check console for details.</div>'
);
}
</script>
<style>
.chart-container {
min-height: 400px;
/* Making sure it looks good and accessible */
--chart-background: theme('colors.white');
--chart-text: theme('colors.gray.900');
}
@media (prefers-reduced-motion: reduce) {
.chart-container {
--chart-animation-duration: 0s;
}
}
</style>
What Makes This Component Different
Let me break down what’s happening here, because there’s more going on than meets the eye:
Unique IDs for everything. Each chart gets its own container, which means you can have as many as you want without them stepping on each other’s toes.
Built-in error handling. Because let’s face it, JSON parsing can go wrong, and when it does, you want to know about it instead of staring at a blank div wondering what happened.
Accessibility baked in. Screen readers can actually understand what your charts are showing, which is something most people forget about.
Responsive by default. The charts adapt to their container, so they’ll look good on mobile without extra work.
Putting It All Together
Want to see multiple charts in action? Here’s how you’d use this component:
<ChartsComponent
chartId="line-chart"
title="Sales Growth"
description="Monthly sales data for the past year"
chart={`
{
"chart": {
"type": "line",
"height": 350
},
"series": [{
"name": "Sales",
"data": [30, 40, 35, 50, 49, 60, 70, 91, 125]
}],
"xaxis": {
"categories": [1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999]
},
"colors": ["#1f77b4"]
}
`}
/>
And here’s what that looks like:
Sales Growth
Monthly sales data for the past year
Clean, simple, and it actually works.
📊 JSON Gotcha
The Real Talk Section
Look, I’m not gonna sugarcoat this—getting charts to play nice with Astro’s build process can be a bit finicky at first. You might run into hydration issues, or your charts might render fine in development but break in production.
Here’s what I’ve learned from building this stuff:
Always test your chart configs in isolation first. Build a simple HTML file with just ApexCharts and your data. Get it working there, then bring it into Astro.
Watch out for SSR issues. Since charts need the DOM to exist, make sure you’re waiting for DOMContentLoaded
before trying to render anything.
Keep your data simple initially. Start with basic arrays and objects. You can always make it more complex once you’ve got the foundation solid.
⚡ Performance Tip
Where to Go From Here
Once you’ve got the basics down, ApexCharts opens up a whole world of possibilities. You can build real-time dashboards, interactive data explorers, or just make your blog posts way more engaging with some slick visualizations.
The component I’ve shown you here is just the starting point. You could extend it to handle themes, add export functionality, or even connect it to your CMS for dynamic chart generation.
But honestly? Start simple. Get one chart working perfectly, then expand from there. There’s nothing worse than over-engineering something that should be straightforward.
And that’s it! You’ve now got everything you need to add professional-looking charts to your Astro site. The best part? Your visitors will think you’re some kind of data visualization wizard, when really you just followed a tutorial from some random developer’s blog.
Now go forth and chart all the things.
Stay up to date
Get notified when I publish something new, and unsubscribe at any time.