spb/svgarden Public
SVGarden — searchable bank of 74 self-contained SVG+CSS animation snippets (svgarden.dev)
HTML 79.2%
Astro 10.3%
JavaScript 6%
CSS 3.7%
Shell 0.8%
1<!--2 ============================================================3 SVGarden — https://www.svgarden.dev4 Author : Simon-Pierre Boucher5 Contact: contact@spboucher.ai6 File : snippets/gauges/gauge-circle.html7 Desc : Circular percentage gauge driven by a range slider (JS)8 ============================================================9-->10<!--svgarden11title: Circle gauge12slug: gauge-circle13category: gauges14tags: [gauge, percentage, slider, js]15difficulty: intermediate16techniques: [pathLength, stroke-dashoffset, css-transition, minimal-js]17how_it_works: >18 With pathLength="100" the circle's circumference *is* 100, so showing v percent19 is just stroke-dashoffset = 100 − v — no trigonometry, no getTotalLength().20 The tiny script only copies the slider value onto that one CSS property and21 the text label; the smooth sweep between values comes for free from a CSS22 transition on stroke-dashoffset. The arc starts at 12 o'clock because the23 whole circle is rotated −90°.24customizable:25 - { var: "--sg-color", label: "Color", type: color, default: "#7F77DD" }26 - { var: "--sg-size", label: "Size", type: range, min: 80, max: 220, default: 130, unit: px }27created: 2026-08-1028-->29<div class="sg-gauge-circle" style="--sg-color:#7F77DD; --sg-size:130px;">30 <svg viewBox="0 0 100 100" role="img" aria-label="Percentage gauge">31 <title>Percentage gauge</title>32 <circle class="sg-gauge-circle-track" cx="50" cy="50" r="44" pathLength="100" />33 <circle class="sg-gauge-circle-arc" cx="50" cy="50" r="44" pathLength="100" />34 <text class="sg-gauge-circle-value" x="50" y="57">67%</text>35 </svg>36 <input class="sg-gauge-circle-slider" type="range" min="0" max="100" value="67" aria-label="Gauge value" />37</div>38<script>39 document.querySelectorAll('.sg-gauge-circle:not([data-sg-init])').forEach(function (root) {40 root.setAttribute('data-sg-init', '');41 var arc = root.querySelector('.sg-gauge-circle-arc');42 var label = root.querySelector('.sg-gauge-circle-value');43 var slider = root.querySelector('.sg-gauge-circle-slider');44 function render() {45 arc.style.strokeDashoffset = 100 - slider.value;46 label.textContent = slider.value + '%';47 }48 slider.addEventListener('input', render);49 render();50 });51</script>52<style>53 .sg-gauge-circle {54 width: var(--sg-size);55 display: flex;56 flex-direction: column;57 gap: 0.6rem;58 align-items: center;59 }60 .sg-gauge-circle svg {61 width: 100%;62 display: block;63 }64 .sg-gauge-circle-track,65 .sg-gauge-circle-arc {66 fill: none;67 stroke-width: 8;68 stroke-linecap: round;69 transform: rotate(-90deg);70 transform-origin: 50% 50%;71 }72 .sg-gauge-circle-track {73 stroke: var(--sg-color);74 opacity: 0.15;75 }76 .sg-gauge-circle-arc {77 stroke: var(--sg-color);78 stroke-dasharray: 100;79 stroke-dashoffset: 33;80 transition: stroke-dashoffset 0.45s ease;81 }82 .sg-gauge-circle-value {83 font-family: inherit;84 font-size: 20px;85 font-weight: 600;86 fill: currentColor;87 text-anchor: middle;88 }89 .sg-gauge-circle-slider {90 width: 90%;91 accent-color: var(--sg-color);92 }93</style>94