[![Image shows a minimalist vertical bar chart with 7 vertically-oriented "pill" shaped bars. Each bar consists of:
An outer container:
An inner fill bar:
The bars are evenly spaced with approximately 20px between them. No axis lines, labels, or grid are shown. The first bar shows dimensions of 145.58 x 15.91 pixels. The overall effect is clean and modern, with each bar appearing as a gray pill partially filled from the bottom with blue.](https://i.sstatic.net/BOqHlTLz.png)](https://i.sstatic.net/BOqHlTLz.png)
I'm trying to create a vertical bar chart in Vue.js that has a specific design: each bar should have a light gray rounded container with a blue fill bar inside it. Here's what I'm trying to achieve:
[Image description: A bar chart with 7 vertical bars. Each bar has a light gray (#E9EDF7) rounded container that extends full height, with a blue (#1A75FF) rounded bar inside it showing the actual value. The bars appear to have significant border radius, giving them a pill-like shape.]
Here's my current attempt:
<template>
<div class="p-4">
<ClientOnly>
<apexchart type="bar" :options="chartOptions" :series="series" height="250" />
</ClientOnly>
</div>
</template>
<script lang="ts" setup>
import { ref } from "vue";
const series = ref([
{
name: "Value",
data: [80, 40, 70, 35, 60, 85, 25]
}
]);
const chartOptions = ref({
chart: {
type: "bar",
toolbar: {
show: false
}
},
plotOptions: {
bar: {
borderRadius: 20,
columnWidth: "25%"
}
},
grid: {
show: false
},
xaxis: {
labels: {
show: false
}
},
yaxis: {
show: false
}
});
</script>
However, I can't figure out how to:
Create the gray container effect for each bar Get the proper rounded corners on both the container and fill bar Maintain consistent spacing between the bars
I'm using:
Vue 3 ApexCharts (vue3-apexcharts) TypeScript
Has anyone achieved something similar? I'd appreciate any guidance on how to create this effect.
To set bar and bar container colors, use the colors
and plotOptions.bar.colors.backgroundBarColors
option:
const chartOptions = ref({
...
colors: ['#1A75FF'],
plotOptions: {
bar: {
colors: {
backgroundBarColors: ['#e7ebf5'],
}
}
},
Similarly, you can set radius with the options plotOptions.bar.borderRadius
and plotOptions.bar.colors.backgroundBarRadius
:
const chartOptions = ref({
plotOptions: {
bar: {
borderRadius: 15,
colors: {
backgroundBarRadius: 15,
}
}
},
Note thatborderRadius
expects a pixel value. So unless you use fixed width, the value has to adjust for evenly rounded corners on different container/screen sizes.
One way to do this is in the updated event. It receives the chart object as parameter, so you can check radius and update it if necessary:
const updateRadius = (chart) => {
const barWidth = chart.w.globals.barWidth
const expectedRadius = 0.5 * barWidth
const currentRadius = chart.w.config.plotOptions.bar.borderRadius
if (currentRadius !== expectedRadius) { // <--- endless loop if you screw this up
const optionsUpdate = {
plotOptions: {
bar: {
borderRadius: expectedRadius,
colors: {
backgroundBarRadius: expectedRadius,
}
}
}
}
chart.updateOptions(optionsUpdate, false, false)
}
}
For other approaches (like ResizeObserver) you need a reference to the chart object, which is exposed by the apexchart component:
<template>
<apexchart type="bar" ref="apexRef"/>
</template>
<script setup>
const apexRef = ref() // bind template ref
const chart = computed(() => apexRef.value.chart) // access exposed chart object
</script>
Here it is in playground