Skip to content
Knsept
Free playbook

Count-up stats

Numbers that count up when they scroll into view, with easing and formatting. A quicker count with reduced motion.

JavaScriptUI Widgets Updated Oct 23, 2026
Live demo Reduced motion is on, so effects are toned down
<div class="count-demo">
  <div class="stats">
    <div class="stat"><b data-count-to="1284">1,284</b><span>Builds shipped</span></div>
    <div class="stat"><b data-count-to="99.9" data-decimals="1" data-suffix="%">99.9%</b><span>Uptime</span></div>
    <div class="stat"><b data-count-to="42000" data-prefix="$">$42,000</b><span>Saved on hosting</span></div>
  </div>
  <button class="replay-count" type="button">Count again</button>
</div>

Each number counts once, the first time it's on screen, thanks to an IntersectionObserver that stops watching after it fires. font-variant-numeric: tabular-nums gives every digit the same width, so the number doesn't jitter while it counts.

The HTML ships with the final numbers, and the script only resets them to zero once it's running. So if JavaScript fails or loads late, visitors still see the real values, never a row of zeros.

toLocaleString() adds thousands separators in the visitor's own format (1,284 or 1.284). Prefix, suffix and decimals come from data attributes, so one script handles money, percentages and plain counts.

With reduced motion on, the count still runs, just faster (half a second instead of 1.6).

More from the library

Scroll & motion live

Reveal on scroll

Content that fades and rises into place as it enters the viewport, with staggered timing and no layout shift.

Scroll & motion live

Scroll progress bar

A reading progress bar driven entirely by CSS scroll timelines, with a small JS fallback.

Navigation live

Smooth accordion

A FAQ accordion built on native details/summary, with a smooth open and close animation and an optional one-open-at-a-time mode.