2.10 · Animation

Animated
Number Counter.

Stats sit at zero until the section enters the viewport, then tick up to their target over ~1.8s. The signature "by-the-numbers" moment on every modern marketing page.

What it is

When a stats section scrolls into view, the numbers visibly count from zero up to their final value over about 1.5 to 2 seconds with an ease-out curve. It's a small, slightly theatrical detail — but it consistently makes the reader pause on the impressive numbers instead of skimming past them. Used by GitHub, Vercel, every annual-report page, every "by the numbers" section.

How it works

Each number element has a data-target attribute with the final value. An IntersectionObserver watches them — once a stat is at least 30% visible, an animation runs that lerps the displayed value from 0 to the target over ~1800ms, using requestAnimationFrame and an ease-out curve (like 1 - (1-t)^3). The displayed value is formatted with thousand separators (Intl.NumberFormat) and the suffix/prefix (e.g. "k", "%", "$") is rendered as a smaller span next to it.

IntersectionObserverTriggers the count only when the element is genuinely visible
requestAnimationFramePer-frame value updates, ~60fps smooth on every device
Ease-out cubic1 - Math.pow(1 - t, 3) — fast start, gentle stop. Feels theatrical, not robotic.
tabular-numsCSS font-variant-numeric: tabular-nums keeps digits the same width — no jitter
Tip. Only animate once. After the count completes, unobserve the element so scrolling back up doesn't re-trigger the animation (which feels broken).

Live demo

Scroll inside. The stats start at zero — they count up the moment they enter the viewport.

Live · scroll inside
↓ scroll down to trigger

Keep scrolling — the magic happens below.

$0
Funded
Across 47 projects in 2025.
0
Active makers
Up 38% year on year.
0%
Uptime
Measured across 12 months.
0m
Support reply
Median, in business hours.

That's the whole trick — scroll back up to reset.

Copy this prompt

Prompt · 2.10 Animated Number Counter
Build a "by the numbers" stats section with animated counters. Each stat is a 4-column grid item with a giant number (font-size clamp(48px,7vw,84px), font-weight 300, font-variant-numeric:tabular-nums so digits don't jitter) above a small uppercase monospace label. Add an optional prefix ($) or suffix (% / k / m) as a smaller span next to the number. Each number element has data-counter and data-target="X" attributes. Use IntersectionObserver (threshold 0.3) to detect when each stat enters the viewport — on first intersection, run a requestAnimationFrame loop that lerps the displayed value from 0 to data-target over 1800ms with an ease-out-cubic curve (1 - Math.pow(1 - t, 3)). Format the displayed value with Intl.NumberFormat for thousand separators. Unobserve after the animation completes so it doesn't re-trigger on scroll-back. Stat values: $84,000,000 funded · 12,408 active makers · 99.96% uptime · 11m support reply.

Example sites to study