Animated Data Stats
Counters that ease toward their value, eight scroll-triggered progress bars, and five SVG ring gauges that fill on reveal.
Animated Data Stats the 4th of 12 designs in the 12 CSS Scroll 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
This is a full-page demo — interact inside the frame above, or open it in the playground for the full-screen experience.
The code
<!-- S1: BIG COUNTERS -->
<section class="section s1">
<div class="glow s1-glow"></div>
<div class="counter-grid">
<div class="c-card">
<div class="c-num" data-target="4.2" data-suffix="B">0</div>
<div class="c-lbl">Global Users</div>
<div class="c-sub">↑ <span>+18%</span> this quarter</div>
</div>
<div class="c-card">
<div class="c-num" data-target="98.7" data-suffix="%">0</div>
<div class="c-lbl">Uptime SLA</div>
<div class="c-sub">↑ <span>+0.3pp</span> vs last year</div>
</div>
<div class="c-card">
<div class="c-num" data-target="340" data-suffix="ms">0</div>
<div class="c-lbl">Avg Response</div>
<div class="c-sub">↓ <span>-12%</span> latency</div>
</div>
<div class="c-card">
<div class="c-num" data-target="2.1" data-suffix="M">0</div>
<div class="c-lbl">API Calls / sec</div>
<div class="c-sub">↑ <span>+31%</span> throughput</div>
</div>
<div class="c-card">
<div class="c-num" data-target="99.4" data-suffix="%">0</div>
<div class="c-lbl">Data Accuracy</div>
<div class="c-sub">↑ <span>+0.8pp</span> precision</div>
</div>
<div class="c-card">
<div class="c-num" data-target="7" data-suffix="x">0</div>
<div class="c-lbl">Faster Ingestion</div>
<div class="c-sub">↑ vs <span>legacy stack</span></div>
</div>
</div>
</section>
<!-- S2: PROGRESS BARS -->
<section class="section s2">
<div class="glow s2-glow"></div>
<div class="s2-head">Regional coverage</div>
<div class="s2-desc">Market penetration by geography · fiscal year 2024</div>
<div class="bars">
<div class="bar-row" style="--w:91%;--bc:#00C8FF;--bc2:#00E5D0"><div class="br-top"><span class="br-name">Americas</span><span class="br-val">91%</span></div><div class="br-track"><div class="br-fill"></div></div></div>
<div class="bar-row" style="--w:87%;--bc:#39FF14;--bc2:#00E5CC"><div class="br-top"><span class="br-name">APAC</span><span class="br-val">87%</span></div><div class="br-track"><div class="br-fill"></div></div></div>
<div class="bar-row" style="--w:78%;--bc:#A78BFA;--bc2:#C084FC"><div class="br-top"><span class="br-name">Western Europe</span><span class="br-val">78%</span></div><div class="br-track"><div class="br-fill"></div></div></div>
<div class="bar-row" style="--w:73%;--bc:#60A5FA;--bc2:#34D399"><div class="br-top"><span class="br-name">Eastern Europe</span><span class="br-val">73%</span></div><div class="br-track"><div class="br-fill"></div></div></div>
<div class="bar-row" style="--w:62%;--bc:#FBBF24;--bc2:#F59E0B"><div class="br-top"><span class="br-name">ANZ</span><span class="br-val">62%</span></div><div class="br-track"><div class="br-fill"></div></div></div>
<div class="bar-row" style="--w:58%;--bc:#FB7185;--bc2:#F43F5E"><div class="br-top"><span class="br-name">Latam</span><span class="br-val">58%</span></div><div class="br-track"><div class="br-fill"></div></div></div>
<div class="bar-row" style="--w:44%;--bc:#F472B6;--bc2:#E879F9"><div class="br-top"><span class="br-name">MEA</span><span class="br-val">44%</span></div><div class="br-track"><div class="br-fill"></div></div></div>
<div class="bar-row" style="--w:31%;--bc:#94A3B8;--bc2:#64748B"><div class="br-top"><span class="br-name">South Asia</span><span class="br-val">31%</span></div><div class="br-track"><div class="br-fill"></div></div></div>
</div>
</section>
<!-- S3: RING GAUGES -->
<section class="section s3">
<div class="glow s3-glow"></div>
<div class="s3-head">Product health</div>
<div class="s3-desc">Core metrics · rolling 90-day average</div>
<div class="rings">
<div class="ring-item">
<svg width="110" height="110" viewBox="0 0 100 100"><circle class="r-bg" cx="50" cy="50" r="45"/><circle class="r-arc" cx="50" cy="50" r="45" stroke="#39FF14" style="--off:51"/><text class="r-txt" x="50" y="50" fill="#39FF14">82%</text></svg>
<div class="r-label">Conversion</div>
</div>
<div class="ring-item">
<svg width="110" height="110" viewBox="0 0 100 100"><circle class="r-bg" cx="50" cy="50" r="45"/><circle class="r-arc" cx="50" cy="50" r="45" stroke="#A78BFA" style="--off:88"/><text class="r-txt" x="50" y="50" fill="#A78BFA">69%</text></svg>
<div class="r-label">Retention</div>
</div>
<div class="ring-item">
<svg width="110" height="110" viewBox="0 0 100 100"><circle class="r-bg" cx="50" cy="50" r="45"/><circle class="r-arc" cx="50" cy="50" r="45" stroke="#00C8FF" style="--off:20"/><text class="r-txt" x="50" y="50" fill="#00C8FF">93%</text></svg>
<div class="r-label">Satisfaction</div>
</div>
<div class="ring-item">
<svg width="110" height="110" viewBox="0 0 100 100"><circle class="r-bg" cx="50" cy="50" r="45"/><circle class="r-arc" cx="50" cy="50" r="45" stroke="#FBBF24" style="--off:139"/><text class="r-txt" x="50" y="50" fill="#FBBF24">51%</text></svg>
<div class="r-label">Growth MoM</div>
</div>
<div class="ring-item">
<svg width="110" height="110" viewBox="0 0 100 100"><circle class="r-bg" cx="50" cy="50" r="45"/><circle class="r-arc" cx="50" cy="50" r="45" stroke="#FB7185" style="--off:34"/><text class="r-txt" x="50" y="50" fill="#FB7185">88%</text></svg>
<div class="r-label">NPS Score</div>
</div>
</div>
<div class="detail-grid">
<div class="detail-item"><div class="d-num">14.2K</div><div class="d-lbl">Daily Active</div><div class="d-trend" style="color:#39FF14">+9.4%</div></div>
<div class="detail-item"><div class="d-num">3.8s</div><div class="d-lbl">Session Length</div><div class="d-trend" style="color:#39FF14">+0.3s</div></div>
<div class="detail-item"><div class="d-num">2.1%</div><div class="d-lbl">Churn Rate</div><div class="d-trend" style="color:#39FF14">−0.4pp</div></div>
<div class="detail-item"><div class="d-num">$84</div><div class="d-lbl">Avg Rev/User</div><div class="d-trend" style="color:#39FF14">+$12</div></div>
</div>
</section> *,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
body{background:#030508;overflow-x:hidden;color:#fff}
.section{min-height:100vh;padding:8rem 6vw;position:relative;overflow:hidden}
/* glow */
.glow{
position:absolute;border-radius:50%;pointer-events:none;
background:radial-gradient(circle,var(--gc),transparent 65%);
}
/* S1: COUNTERS */
.s1-glow{
--gc:rgba(57,255,20,0.045);
width:800px;height:800px;
top:50%;left:50%;transform:translate(-50%,-50%);
}
.counter-grid{
display:grid;grid-template-columns:repeat(3,1fr);gap:2rem;
max-width:900px;margin:0 auto;
}
.c-card{
border:1px solid rgba(57,255,20,0.12);border-radius:14px;
padding:2.5rem 2rem;background:rgba(57,255,20,0.015);
opacity:0;transform:translateY(44px);
transition:opacity 0.9s cubic-bezier(0.16,1,0.3,1),transform 0.9s cubic-bezier(0.16,1,0.3,1);
}
.c-card.in{opacity:1;transform:translateY(0)}
.c-card:nth-child(2){transition-delay:0.13s}
.c-card:nth-child(3){transition-delay:0.26s}
.c-num{
font-family:'Space Mono',monospace;font-weight:700;
font-size:clamp(48px,6vw,80px);
color:#39FF14;line-height:1;margin-bottom:0.6rem;
}
.c-lbl{
font-family:'Space Mono',monospace;font-size:11px;
letter-spacing:0.14em;text-transform:uppercase;
color:rgba(255,255,255,0.28);
}
.c-sub{
font-family:'Space Mono',monospace;font-size:11px;
color:rgba(57,255,20,0.45);margin-top:1rem;
}
.c-sub span{color:#39FF14}
/* S2: BARS */
.s2{background:#040608}
.s2-glow{
--gc:rgba(0,200,255,0.035);
width:700px;height:700px;
top:40%;left:30%;transform:translate(-50%,-50%);
}
.s2-head{
font-family:'Syne',sans-serif;font-weight:800;
font-size:clamp(28px,4vw,48px);
margin-bottom:0.5rem;
opacity:0;transform:translateX(-30px);
transition:opacity 0.8s ease,transform 0.8s cubic-bezier(0.16,1,0.3,1);
}
.s2-head.in{opacity:1;transform:translateX(0)}
.s2-desc{
font-family:'Space Mono',monospace;font-size:12px;
color:rgba(0,200,255,0.5);margin-bottom:4rem;
opacity:0;transition:opacity 0.7s ease 0.3s;
}
.s2-desc.in{opacity:1}
.bars{display:flex;flex-direction:column;gap:2rem;max-width:760px}
.bar-row{
opacity:0;transform:translateX(-28px);
transition:opacity 0.7s ease,transform 0.7s cubic-bezier(0.16,1,0.3,1);
}
.bar-row.in{opacity:1;transform:translateX(0)}
.bar-row:nth-child(2){transition-delay:0.08s}
.bar-row:nth-child(3){transition-delay:0.16s}
.bar-row:nth-child(4){transition-delay:0.24s}
.bar-row:nth-child(5){transition-delay:0.32s}
.bar-row:nth-child(6){transition-delay:0.40s}
.bar-row:nth-child(7){transition-delay:0.48s}
.bar-row:nth-child(8){transition-delay:0.56s}
.br-top{display:flex;justify-content:space-between;align-items:baseline;margin-bottom:8px}
.br-name{font-family:'Space Mono',monospace;font-size:12px;color:rgba(255,255,255,0.4)}
.br-val{font-family:'Space Mono',monospace;font-size:12px;color:var(--bc)}
.br-track{height:4px;background:rgba(255,255,255,0.05);border-radius:2px;overflow:hidden}
.br-fill{
height:100%;border-radius:2px;width:0%;
background:linear-gradient(to right,var(--bc),var(--bc2));
transition:width 1.4s cubic-bezier(0.16,1,0.3,1) 0.1s;
}
.bar-row.in .br-fill{width:var(--w)}
/* S3: RINGS + DETAILED STATS */
.s3{background:#030407}
.s3-glow{
--gc:rgba(170,80,255,0.04);
width:700px;height:700px;
top:50%;left:60%;transform:translate(-50%,-50%);
}
.s3-head{
font-family:'Syne',sans-serif;font-weight:800;
font-size:clamp(28px,4vw,48px);margin-bottom:0.5rem;
opacity:0;transform:translateX(-30px);
transition:opacity 0.8s ease,transform 0.8s cubic-bezier(0.16,1,0.3,1);
}
.s3-head.in{opacity:1;transform:translateX(0)}
.s3-desc{
font-family:'Space Mono',monospace;font-size:12px;
color:rgba(170,80,255,0.5);margin-bottom:5rem;
opacity:0;transition:opacity 0.7s ease 0.3s;
}
.s3-desc.in{opacity:1}
.rings{display:flex;gap:3.5rem;flex-wrap:wrap;justify-content:center;margin-bottom:5rem}
.ring-item{
display:flex;flex-direction:column;align-items:center;gap:1rem;
opacity:0;transform:scale(0.65);
transition:opacity 0.9s ease,transform 0.9s cubic-bezier(0.16,1,0.3,1);
}
.ring-item.in{opacity:1;transform:scale(1)}
.ring-item:nth-child(2){transition-delay:0.15s}
.ring-item:nth-child(3){transition-delay:0.30s}
.ring-item:nth-child(4){transition-delay:0.45s}
.ring-item:nth-child(5){transition-delay:0.60s}
.r-bg{fill:none;stroke:rgba(255,255,255,0.06);stroke-width:8}
.r-arc{
fill:none;stroke-width:8;stroke-linecap:round;
stroke-dasharray:283;stroke-dashoffset:283;
transform-box:fill-box;transform-origin:center;
transform:rotate(-90deg);
transition:stroke-dashoffset 1.7s cubic-bezier(0.16,1,0.3,1) 0.15s;
}
.ring-item.in .r-arc{stroke-dashoffset:var(--off)}
.r-label{
font-family:'Space Mono',monospace;font-size:10px;
color:rgba(255,255,255,0.28);text-transform:uppercase;
letter-spacing:0.1em;text-align:center;
}
.r-txt{font-family:'Space Mono',monospace;font-size:15px;font-weight:700;text-anchor:middle;dominant-baseline:middle}
/* detail row */
.detail-grid{
display:grid;grid-template-columns:repeat(4,1fr);gap:1.5rem;
max-width:800px;margin:0 auto;
}
.detail-item{
text-align:center;
opacity:0;transform:translateY(24px);
transition:opacity 0.7s ease,transform 0.7s cubic-bezier(0.16,1,0.3,1);
}
.detail-item.in{opacity:1;transform:translateY(0)}
.detail-item:nth-child(2){transition-delay:0.1s}
.detail-item:nth-child(3){transition-delay:0.2s}
.detail-item:nth-child(4){transition-delay:0.3s}
.d-num{
font-family:'Space Mono',monospace;font-size:clamp(22px,2.5vw,34px);
font-weight:700;color:#fff;margin-bottom:0.4rem;
}
.d-lbl{font-family:'Space Mono',monospace;font-size:10px;color:rgba(255,255,255,0.28);text-transform:uppercase;letter-spacing:0.1em}
.d-trend{font-family:'Space Mono',monospace;font-size:11px;margin-top:0.4rem} function animCount(el){
const target=parseFloat(el.dataset.target);
const suffix=el.dataset.suffix||'';
const dec=String(target).includes('.');
const dur=1900,start=performance.now();
const tick=now=>{
const p=Math.min((now-start)/dur,1);
const ease=1-Math.pow(1-p,4);
el.textContent=(dec?(ease*target).toFixed(1):Math.round(ease*target))+suffix;
if(p<1)requestAnimationFrame(tick);
};
requestAnimationFrame(tick);
}
const io=new IntersectionObserver(entries=>{
entries.forEach(e=>{
if(!e.isIntersecting)return;
e.target.classList.add('in');
const n=e.target.querySelector('.c-num');
if(n&&!n.dataset.done){n.dataset.done='1';animCount(n);}
});
},{threshold:0.2});
document.querySelectorAll('.c-card,.s2-head,.s2-desc,.bar-row,.s3-head,.s3-desc,.ring-item,.detail-item')
.forEach(el=>io.observe(el));