ApexCharts Radial Bar Goal Rings — Free Activity Rings Snippet

ApexCharts Radial Bar Goal Rings · Charts · Plain HTML, CSS & JS · Live preview

CategoryCharts

What's included

Features

Concentric goal rings
One radialBar ring per goal, drawn as a full circle.
Values kept separate from ratios
Real units in data, percentages in the chart.
Over-target capping
Exceeded goals draw a complete ring, never more.
Overall centre label
A total formatter averages all rings when idle.
Rounded progress ends
stroke.lineCap: 'round' for an activity-ring look.
Animated updates
updateSeries animates each ring to its new angle.
Text equivalent
A list repeats every value for readers who can't rely on colour.
Dark theme styling
Tracks and labels tuned for a dark card.

About this UI Snippet

ApexCharts Radial Bar Goal Rings — Several Targets, One Compact Chart

Screenshot of the ApexCharts Radial Bar Goal Rings snippet rendered live

Goal rings are a good fit when a handful of targets matter equally and each has a different unit: calories, minutes and hours can't share an axis, but "how far along am I" can. ApexCharts' radialBar chart draws one concentric ring per series value, which maps directly onto that idea.

The chart only ever sees percentages

A radial bar value is a percentage from 0 to 100. The snippet keeps real values and targets in a GOALS array and derives percentages with percents(). That separation matters: the side list shows "1,840 / 2,500 kcal" from the real data, and the chart shows the ratio, so neither has to be reverse-engineered from the other. Values are capped at 100 so an exceeded goal draws a full ring rather than a broken one.

Full circles and rounded ends

startAngle: 0 and endAngle: 360 turn the default gauge into full rings. stroke.lineCap: 'round' rounds the ends of each progress arc, and track styles the unfilled remainder of each ring.

A meaningful centre label

dataLabels.total shows an "Overall" average when nothing is hovered, computed from w.globals.series in its formatter. Hovering a ring swaps the centre to that ring's name and percentage.

Animated updates

"Log a workout" changes the underlying values and calls updateSeries(percents()). ApexCharts animates each ring from its old angle to its new one.

Accessibility

Rings alone are hard to read for people who can't distinguish the colours, so every value is also listed in text beside the chart with a matching colour dot.

Step by step

How to Use

  1. 1
    Load ApexChartsInclude apexcharts.min.js from the CDN.
  2. 2
    Paste the snippetThree concentric rings render next to a text list of the same values.
  3. 3
    Hover a ringThe centre label switches from the overall average to that ring.
  4. 4
    Log progressClick the button; the rings animate to their new percentages.
  5. 5
    Define your goalsEdit the GOALS array: name, unit, current value, target and colour.

Real-world uses

Common Use Cases

Fitness and health apps
Show move, exercise and stand goals as concentric rings, each tracking its own target in its own unit and all readable at a glance.
Sales quotas
Track per-rep or per-region progress against quota. Over-target goals draw a complete ring and never more, so the chart stays honest.
Project health
Show budget used, tasks done and time elapsed together. Percentages live in the chart while real units stay in the data, so labels can show both.
Learning platform progress
Display course, quiz and practice completion as rings, with the centre label averaging all of them into one overall figure while idle.
Habit and savings dashboards
Use rings for goals with different units, such as calories, minutes and money, which cannot share an axis but can share a percentage.
Related: Activity Rings (vanilla SVG)
See how the same idea is built without a library in Activity Rings.
Related: ApexCharts Sparkline KPI Cards
Show trends next to goals with ApexCharts Sparkline KPI Cards.

Got questions?

Frequently Asked Questions

Percentages between 0 and 100, one per ring. Convert real values yourself, for example Math.round(value / target * 100), and keep the originals in your own data for labels and tooltips.

Set plotOptions.radialBar.startAngle to 0 and endAngle to 360. For a semicircle gauge use -90 and 90 instead.

Enable plotOptions.radialBar.dataLabels.total with show: true, a label, and a formatter. The formatter receives the chart context w; w.globals.series holds the current percentages you can average or sum.

A value above 100 would draw past a full circle, so the snippet caps each percentage at 100. The real value is still shown in the text list, so the overachievement is not lost.

Call chart.updateSeries with the new array of percentages. ApexCharts animates each ring from its previous value; chart.animations.speed controls the duration.

Build with AI

Build, Understand, Optimize, and Extend It With AI

Paste this snippet into Claude or another AI assistant and ask it to explain why the chart receives percentages while the list shows real values, and how the total formatter reads the current series. It can help you add a celebratory state when a ring reaches 100%, weekly history as small rings per day, or a light theme variant. Ask whether capping at 100% hides useful information and how you might show overachievement instead, such as a second lap ring.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build concentric goal progress rings with the ApexCharts radialBar chart (loaded from a CDN) in plain HTML, CSS and JavaScript on a dark card.

Requirements:
- Keep three goals in a data array, each with a name, unit, current value, target and colour.
- Convert each goal to a percentage of its target, capped at 100, and pass only percentages to the chart.
- Draw full-circle rings with rounded line caps, a dim track behind each ring and a hollow centre.
- Show an "Overall" average in the centre when idle, and the hovered ring's name and percentage on hover.
- List every goal beside the chart as text with a colour dot, current value, target and unit.
- Add a "Log a workout" button that increases the values and animates the rings with updateSeries.
- Stack the chart and list vertically on narrow screens.

Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.

Source Code

Requires
<div class="arg-wrap">
  <div class="arg-card">
    <div class="arg-title">Weekly Goals</div>
    <div class="arg-sub">Each ring is progress toward its own target</div>
    <div class="arg-body">
      <div id="argChart"></div>
      <ul class="arg-list" id="argList"></ul>
    </div>
    <button class="arg-btn" id="argLog" type="button">Log a workout</button>
  </div>
</div>