15 CSS Number Counter Animations
Fitness Step Counter
Warm pastel scene with morphing blob shapes in the background. A circular gradient ring fills to 75% with a bouncing flame at the center. The step count springs up with a playful overshoot. Milestone pills mark 5K and 7.5K as done, 10K actively pulsing. Built for health apps and wearable dashboards.
Fitness Step Counter the 9th of 15 designs in the 15 CSS Number Counter Animations collection. The design pairs CSS styling with a small amount of JavaScript for interactivity. Copy the HTML, CSS and JavaScript panels below into your project — the JS is self-contained, has zero dependencies, and is safe to drop into any framework (React, Vue, Svelte, plain HTML). The design honours prefers-reduced-motion and uses real semantic markup, so it ships accessibility-ready out of the box.
Live preview
The code
<div class="cnc-fit">
<div class="cnc-fit-shape cnc-fit-s1"></div>
<div class="cnc-fit-shape cnc-fit-s2"></div>
<div class="cnc-fit-shape cnc-fit-s3"></div>
<div class="cnc-fit-block">
<div class="cnc-fit-day-label">Tuesday · May 19</div>
<div class="cnc-fit-ring-outer">
<svg class="cnc-fit-ring-svg" width="220" height="220" viewBox="0 0 220 220">
<defs><linearGradient id="cnc-fit-ringGrad" x1="0%" y1="0%" x2="100%" y2="0%"><stop offset="0%" stop-color="#ffaa66"/><stop offset="100%" stop-color="#ff4e4e"/></linearGradient></defs>
<circle class="cnc-fit-ring-track" cx="110" cy="110" r="95"/>
<circle class="cnc-fit-ring-prog" cx="110" cy="110" r="95"/>
</svg>
<div class="cnc-fit-ring-center">
<div class="cnc-fit-ring-emoji">🔥</div>
<div class="cnc-fit-ring-num"><span class="cnc-fit-pct" data-target="75">0</span>%</div>
<div class="cnc-fit-ring-unit">of goal</div>
</div>
</div>
<div class="cnc-fit-step-num" data-steps data-target="7534">0</div>
<div class="cnc-fit-step-label">Steps Today</div>
<div class="cnc-fit-milestones">
<div class="cnc-fit-ms cnc-fit-ms-done">5K</div>
<div class="cnc-fit-ms cnc-fit-ms-done">7.5K</div>
<div class="cnc-fit-ms cnc-fit-ms-active">10K</div>
<div class="cnc-fit-ms cnc-fit-ms-next">15K</div>
</div>
</div>
</div> .cnc-fit { min-height: 540px; display: grid; place-items: center; padding: 48px 24px; background: #fff4e6; position: relative; overflow: hidden; font-family: 'Nunito', sans-serif; }
.cnc-fit *, .cnc-fit *::before, .cnc-fit *::after { box-sizing: border-box; }
.cnc-fit-shape { position: absolute; pointer-events: none; }
.cnc-fit-s1 { width: 320px; height: 320px; background: #ffe0c2; top: -80px; right: -80px; border-radius: 40% 60% 55% 45%; animation: cnc-fit-morph 10s ease-in-out infinite; }
.cnc-fit-s2 { width: 240px; height: 240px; background: #ffd0f0; bottom: -60px; left: -60px; border-radius: 60% 40% 45% 55%; animation: cnc-fit-morph 14s ease-in-out infinite reverse; }
.cnc-fit-s3 { width: 140px; height: 140px; background: #c8f0e0; top: 30%; right: 5%; border-radius: 55% 45%; animation: cnc-fit-morph 8s ease-in-out infinite; opacity: 0.7; }
@keyframes cnc-fit-morph { 0%, 100% { border-radius: 60% 40% 55% 45%; } 50% { border-radius: 40% 60% 45% 55%; } }
.cnc-fit-block { position: relative; z-index: 1; text-align: center; padding: 32px; width: 420px; max-width: 100%; }
.cnc-fit-day-label { font-size: 11px; letter-spacing: 3px; text-transform: uppercase; color: #ffaa66; font-weight: 700; margin-bottom: 28px; opacity: 0; animation: cnc-fit-pop 0.5s cubic-bezier(0.34,1.56,0.64,1) 0.0s forwards; }
.cnc-fit-ring-outer { width: 220px; height: 220px; margin: 0 auto 24px; position: relative; opacity: 0; animation: cnc-fit-pop 0.7s cubic-bezier(0.34,1.56,0.64,1) 0.15s forwards; }
.cnc-fit-ring-svg { transform: rotate(-90deg); overflow: visible; }
.cnc-fit-ring-track { fill: none; stroke: #ffe8d0; stroke-width: 14; stroke-linecap: round; }
.cnc-fit-ring-prog { fill: none; stroke: url(#cnc-fit-ringGrad); stroke-width: 14; stroke-linecap: round; stroke-dasharray: 597; stroke-dashoffset: 597; filter: drop-shadow(0 0 8px rgba(255,130,60,0.4)); animation: cnc-fit-ringFill 2s cubic-bezier(0.22,1,0.36,1) 0.5s forwards; }
@keyframes cnc-fit-ringFill { to { stroke-dashoffset: 149; } }
.cnc-fit-ring-center { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; }
.cnc-fit-ring-emoji { font-size: 38px; animation: cnc-fit-bounce 2s ease-in-out infinite; line-height: 1; margin-bottom: 4px; }
@keyframes cnc-fit-bounce { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-6px); } }
.cnc-fit-ring-num { font-family: 'Righteous', sans-serif; font-size: 32px; color: #222; letter-spacing: -1px; line-height: 1; }
.cnc-fit-ring-unit { font-size: 10px; letter-spacing: 2px; text-transform: uppercase; color: #ccc; font-weight: 700; margin-top: 3px; }
.cnc-fit-step-num { font-family: 'Righteous', sans-serif; font-size: clamp(64px, 14vw, 88px); color: #1a1a1a; letter-spacing: -2px; line-height: 1; opacity: 0; animation: cnc-fit-pop 0.8s cubic-bezier(0.34,1.56,0.64,1) 0.3s forwards; display: inline-block; }
.cnc-fit-step-label { font-size: 11px; letter-spacing: 3px; text-transform: uppercase; color: #ccc; font-weight: 700; margin-top: 4px; margin-bottom: 28px; opacity: 0; animation: cnc-fit-pop 0.5s ease 0.45s forwards; }
.cnc-fit-milestones { display: flex; gap: 8px; justify-content: center; opacity: 0; animation: cnc-fit-pop 0.5s ease 0.55s forwards; }
.cnc-fit-ms { padding: 8px 16px; border-radius: 100px; font-size: 12px; font-weight: 700; display: flex; align-items: center; gap: 6px; border: 2px solid transparent; }
.cnc-fit-ms-done { background: #fff; border-color: #22c55e; color: #22c55e; }
.cnc-fit-ms-done::before { content: '✓'; }
.cnc-fit-ms-next { background: #fff; border-color: #e0e0e0; color: #ccc; }
.cnc-fit-ms-active { background: #ff823c; color: #fff; animation: cnc-fit-pulse 1.5s ease-in-out infinite; }
@keyframes cnc-fit-pulse { 0%, 100% { box-shadow: 0 0 0 0 rgba(255,130,60,0.4); } 50% { box-shadow: 0 0 0 8px rgba(255,130,60,0); } }
@keyframes cnc-fit-pop { from { opacity: 0; transform: scale(0.85); } to { opacity: 1; transform: scale(1); } }
@media (prefers-reduced-motion: reduce) {
.cnc-fit-shape, .cnc-fit-day-label, .cnc-fit-ring-outer, .cnc-fit-ring-prog, .cnc-fit-ring-emoji, .cnc-fit-step-num, .cnc-fit-step-label, .cnc-fit-milestones, .cnc-fit-ms-active { animation: none; opacity: 1; transform: none; }
.cnc-fit-ring-prog { stroke-dashoffset: 149; }
} (function () {
var root = document.querySelector('.cnc-fit');
if (!root) return;
function ease(t) { return 1 - Math.pow(1 - t, 4); }
setTimeout(function () {
var start = performance.now(), dur = 2200;
var stepsEl = root.querySelector('[data-steps]');
var pctEl = root.querySelector('.cnc-fit-pct');
var GOAL = 10000;
var stepsTarget = parseFloat(stepsEl.dataset.target);
function tick(now) {
var t = Math.min((now - start) / dur, 1), e = ease(t), v = e * stepsTarget;
stepsEl.textContent = Math.round(v).toLocaleString();
pctEl.textContent = Math.round(v / GOAL * 100);
if (t < 1) requestAnimationFrame(tick);
}
requestAnimationFrame(tick);
}, 300);
})();