Progress Circle
Circular SVG progress indicators with sizes, colors, indeterminate spinner, and semi-circle variant.
Basic Progress Circle
Preview
70%
Complete
<div class="progress-circle">
<svg class="progress-circle-svg" viewBox="0 0 120 120">
<circle class="progress-circle-bg" cx="60" cy="60" r="54" />
<circle class="progress-circle-fill" cx="60" cy="60" r="54"
stroke-dasharray="339.292" stroke-dashoffset="101.788"
style="--circumference: 339.292" />
</svg>
<div class="progress-circle-content">
<span class="progress-circle-value">70%</span>
<span class="progress-circle-label">Complete</span>
</div>
</div> Requires: ux.min.css
<div class="relative inline-flex items-center justify-center" style="width: 120px; height: 120px">
<svg class="w-full h-full -rotate-90" viewBox="0 0 120 120">
<circle cx="60" cy="60" r="54" fill="none" stroke-width="8" class="stroke-base-200" />
<circle cx="60" cy="60" r="54" fill="none" stroke-width="8"
class="stroke-primary" stroke-linecap="round"
stroke-dasharray="339.292" stroke-dashoffset="101.788" />
</svg>
<div class="absolute flex flex-col items-center justify-center text-center">
<span class="text-[1.75rem] font-bold leading-none tabular-nums">70%</span>
<span class="text-xs text-base-content/60 mt-0.5">Complete</span>
</div>
</div> Requires: tw.min.css
// Calculate stroke-dasharray and stroke-dashoffset:
// const radius = 54;
// const circumference = 2 * Math.PI * radius; // 339.292
// const offset = circumference * (1 - percent / 100);
// circle.style.strokeDasharray = circumference;
// circle.style.strokeDashoffset = offset; Sizes
Preview
75
75%
Done
75%
Complete
75%
Complete
<div class="flex items-center gap-6 flex-wrap">
<div class="progress-circle progress-circle-xs">
<svg class="progress-circle-svg" viewBox="0 0 48 48">
<circle class="progress-circle-bg" cx="24" cy="24" r="20" />
<circle class="progress-circle-fill" cx="24" cy="24" r="20"
stroke-dasharray="125.664" stroke-dashoffset="31.416" />
</svg>
<div class="progress-circle-content">
<span class="progress-circle-value">75</span>
</div>
</div>
<div class="progress-circle progress-circle-sm">
<svg class="progress-circle-svg" viewBox="0 0 80 80">
<circle class="progress-circle-bg" cx="40" cy="40" r="34" />
<circle class="progress-circle-fill" cx="40" cy="40" r="34"
stroke-dasharray="213.628" stroke-dashoffset="53.407" />
</svg>
<div class="progress-circle-content">
<span class="progress-circle-value">75%</span>
<span class="progress-circle-label">Done</span>
</div>
</div>
<div class="progress-circle">
<svg class="progress-circle-svg" viewBox="0 0 120 120">
<circle class="progress-circle-bg" cx="60" cy="60" r="54" />
<circle class="progress-circle-fill" cx="60" cy="60" r="54"
stroke-dasharray="339.292" stroke-dashoffset="84.823" />
</svg>
<div class="progress-circle-content">
<span class="progress-circle-value">75%</span>
<span class="progress-circle-label">Complete</span>
</div>
</div>
<div class="progress-circle progress-circle-lg">
<svg class="progress-circle-svg" viewBox="0 0 160 160">
<circle class="progress-circle-bg" cx="80" cy="80" r="72" />
<circle class="progress-circle-fill" cx="80" cy="80" r="72"
stroke-dasharray="452.389" stroke-dashoffset="113.097" />
</svg>
<div class="progress-circle-content">
<span class="progress-circle-value">75%</span>
<span class="progress-circle-label">Complete</span>
</div>
</div>
</div> Requires: ux.min.css
<div class="flex items-center gap-6 flex-wrap">
<!-- xs: 48px -->
<div class="relative inline-flex items-center justify-center" style="width: 48px; height: 48px">
<svg class="w-full h-full -rotate-90" viewBox="0 0 48 48">
<circle cx="24" cy="24" r="20" fill="none" stroke-width="4" class="stroke-base-200" />
<circle cx="24" cy="24" r="20" fill="none" stroke-width="4"
class="stroke-primary" stroke-linecap="round"
stroke-dasharray="125.664" stroke-dashoffset="31.416" />
</svg>
<div class="absolute flex flex-col items-center justify-center text-center">
<span class="text-sm font-bold leading-none tabular-nums">75</span>
</div>
</div>
<!-- sm: 80px -->
<div class="relative inline-flex items-center justify-center" style="width: 80px; height: 80px">
<svg class="w-full h-full -rotate-90" viewBox="0 0 80 80">
<circle cx="40" cy="40" r="34" fill="none" stroke-width="6" class="stroke-base-200" />
<circle cx="40" cy="40" r="34" fill="none" stroke-width="6"
class="stroke-primary" stroke-linecap="round"
stroke-dasharray="213.628" stroke-dashoffset="53.407" />
</svg>
<div class="absolute flex flex-col items-center justify-center text-center">
<span class="text-xl font-bold leading-none tabular-nums">75%</span>
<span class="text-base-content/60 mt-0.5" style="font-size: 0.6875rem">Done</span>
</div>
</div>
<!-- default: 120px -->
<div class="relative inline-flex items-center justify-center" style="width: 120px; height: 120px">
<svg class="w-full h-full -rotate-90" viewBox="0 0 120 120">
<circle cx="60" cy="60" r="54" fill="none" stroke-width="8" class="stroke-base-200" />
<circle cx="60" cy="60" r="54" fill="none" stroke-width="8"
class="stroke-primary" stroke-linecap="round"
stroke-dasharray="339.292" stroke-dashoffset="84.823" />
</svg>
<div class="absolute flex flex-col items-center justify-center text-center">
<span class="text-[1.75rem] font-bold leading-none tabular-nums">75%</span>
<span class="text-xs text-base-content/60 mt-0.5">Complete</span>
</div>
</div>
<!-- lg: 160px -->
<div class="relative inline-flex items-center justify-center" style="width: 160px; height: 160px">
<svg class="w-full h-full -rotate-90" viewBox="0 0 160 160">
<circle cx="80" cy="80" r="72" fill="none" stroke-width="10" class="stroke-base-200" />
<circle cx="80" cy="80" r="72" fill="none" stroke-width="10"
class="stroke-primary" stroke-linecap="round"
stroke-dasharray="452.389" stroke-dashoffset="113.097" />
</svg>
<div class="absolute flex flex-col items-center justify-center text-center">
<span class="text-[2.5rem] font-bold leading-none tabular-nums">75%</span>
<span class="text-sm text-base-content/60 mt-0.5">Complete</span>
</div>
</div>
</div> Requires: tw.min.css
// No JavaScript required for static display Colors
Preview
80%
80%
50%
30%
<div class="flex items-center gap-6 flex-wrap">
<div class="progress-circle progress-circle-sm color-primary">
<svg class="progress-circle-svg" viewBox="0 0 80 80">
<circle class="progress-circle-bg" cx="40" cy="40" r="34" />
<circle class="progress-circle-fill" cx="40" cy="40" r="34"
stroke-dasharray="213.628" stroke-dashoffset="42.726" />
</svg>
<div class="progress-circle-content"><span class="progress-circle-value">80%</span></div>
</div>
<div class="progress-circle progress-circle-sm color-success">
<svg class="progress-circle-svg" viewBox="0 0 80 80">
<circle class="progress-circle-bg" cx="40" cy="40" r="34" />
<circle class="progress-circle-fill" cx="40" cy="40" r="34"
stroke-dasharray="213.628" stroke-dashoffset="42.726" />
</svg>
<div class="progress-circle-content"><span class="progress-circle-value">80%</span></div>
</div>
<div class="progress-circle progress-circle-sm color-warning">
<svg class="progress-circle-svg" viewBox="0 0 80 80">
<circle class="progress-circle-bg" cx="40" cy="40" r="34" />
<circle class="progress-circle-fill" cx="40" cy="40" r="34"
stroke-dasharray="213.628" stroke-dashoffset="106.814" />
</svg>
<div class="progress-circle-content"><span class="progress-circle-value">50%</span></div>
</div>
<div class="progress-circle progress-circle-sm color-error">
<svg class="progress-circle-svg" viewBox="0 0 80 80">
<circle class="progress-circle-bg" cx="40" cy="40" r="34" />
<circle class="progress-circle-fill" cx="40" cy="40" r="34"
stroke-dasharray="213.628" stroke-dashoffset="149.54" />
</svg>
<div class="progress-circle-content"><span class="progress-circle-value">30%</span></div>
</div>
</div> Requires: ux.min.css
<div class="flex items-center gap-6 flex-wrap">
<!-- Primary 80% -->
<div class="relative inline-flex items-center justify-center" style="width: 80px; height: 80px">
<svg class="w-full h-full -rotate-90" viewBox="0 0 80 80">
<circle cx="40" cy="40" r="34" fill="none" stroke-width="6" class="stroke-base-200" />
<circle cx="40" cy="40" r="34" fill="none" stroke-width="6"
class="stroke-primary" stroke-linecap="round"
stroke-dasharray="213.628" stroke-dashoffset="42.726" />
</svg>
<div class="absolute flex flex-col items-center justify-center text-center">
<span class="text-xl font-bold leading-none tabular-nums">80%</span>
</div>
</div>
<!-- Success 80% -->
<div class="relative inline-flex items-center justify-center" style="width: 80px; height: 80px">
<svg class="w-full h-full -rotate-90" viewBox="0 0 80 80">
<circle cx="40" cy="40" r="34" fill="none" stroke-width="6" class="stroke-base-200" />
<circle cx="40" cy="40" r="34" fill="none" stroke-width="6"
class="stroke-success" stroke-linecap="round"
stroke-dasharray="213.628" stroke-dashoffset="42.726" />
</svg>
<div class="absolute flex flex-col items-center justify-center text-center">
<span class="text-xl font-bold leading-none tabular-nums">80%</span>
</div>
</div>
<!-- Warning 50% -->
<div class="relative inline-flex items-center justify-center" style="width: 80px; height: 80px">
<svg class="w-full h-full -rotate-90" viewBox="0 0 80 80">
<circle cx="40" cy="40" r="34" fill="none" stroke-width="6" class="stroke-base-200" />
<circle cx="40" cy="40" r="34" fill="none" stroke-width="6"
class="stroke-warning" stroke-linecap="round"
stroke-dasharray="213.628" stroke-dashoffset="106.814" />
</svg>
<div class="absolute flex flex-col items-center justify-center text-center">
<span class="text-xl font-bold leading-none tabular-nums">50%</span>
</div>
</div>
<!-- Error 30% -->
<div class="relative inline-flex items-center justify-center" style="width: 80px; height: 80px">
<svg class="w-full h-full -rotate-90" viewBox="0 0 80 80">
<circle cx="40" cy="40" r="34" fill="none" stroke-width="6" class="stroke-base-200" />
<circle cx="40" cy="40" r="34" fill="none" stroke-width="6"
class="stroke-error" stroke-linecap="round"
stroke-dasharray="213.628" stroke-dashoffset="149.54" />
</svg>
<div class="absolute flex flex-col items-center justify-center text-center">
<span class="text-xl font-bold leading-none tabular-nums">30%</span>
</div>
</div>
</div> Requires: tw.min.css
// No JavaScript required for colors Indeterminate Spinner
Preview
<div class="progress-circle progress-circle-indeterminate progress-circle-sm">
<svg class="progress-circle-svg" viewBox="0 0 80 80">
<circle class="progress-circle-bg" cx="40" cy="40" r="34" />
<circle class="progress-circle-fill" cx="40" cy="40" r="34" />
</svg>
</div> Requires: ux.min.css
<div class="relative inline-flex items-center justify-center" style="width: 80px; height: 80px">
<svg class="w-full h-full animate-spin" style="animation-duration: 1.5s" viewBox="0 0 80 80">
<circle cx="40" cy="40" r="34" fill="none" stroke-width="6" class="stroke-base-200" />
<circle cx="40" cy="40" r="34" fill="none" stroke-width="6"
class="stroke-primary" stroke-linecap="round"
stroke-dasharray="80, 200" stroke-dashoffset="0" />
</svg>
</div> Requires: tw.min.css
// No JavaScript required - CSS animation handles the spinning | Class | Description |
|---|---|
.progress-circle | Base container (120px) |
.progress-circle-svg | SVG element (rotated -90deg) |
.progress-circle-bg | Background circle track |
.progress-circle-fill | Foreground fill arc |
.progress-circle-content | Center content overlay |
.progress-circle-value | Large percentage text |
.progress-circle-label | Small label under value |
.progress-circle-icon | Icon in center (32px) |
.progress-circle-xs | 48px size |
.progress-circle-sm | 80px size |
.progress-circle-lg | 160px size |
.progress-circle-xl | 200px size |
.progress-circle-thin | 4px stroke |
.progress-circle-thick | 12px stroke |
.progress-circle-animated | Animate fill from 0 |
.progress-circle-indeterminate | Spinner animation |
.progress-circle-semi | Half-circle variant |
.progress-circle-gradient | Use SVG gradient stroke |
.progress-circle.glass | Glass morphism variant |