By Tim King · Updated
Animated Counter CSS and JS
Count-Up Number Animation in CSS @property or Short JavaScript
OneTask is free, with no sign-up, and built by one person.
If this tool saved you time, a coffee helps keep new ones coming.
How the Animated Counter works
This animated counter CSS and JavaScript builder saves writing it by hand. Type the number you want to land on, how long the climb should take and how it should ease,
and the preview counts up from your start value every time a setting changes. Add a prefix such
as a currency symbol or a suffix like % or +, then copy the snippet. You can choose a
CSS-only version that needs no script at all, or a few lines of JavaScript that format the
number with thousands separators as it ticks.
How the animated counter CSS works
Counting numbers are the standard way to make a statistics strip feel alive: "12,500+
customers" reads as a claim, but watching it climb from zero makes the visitor look at it. The
trick has traditionally needed JavaScript because CSS could not animate a number and print it as
text. That changed with @property. Registering a custom property with syntax: "<integer>"
tells the browser the value is a whole number rather than an opaque token, which makes it
animatable in @keyframes. Feeding that property into counter-reset and printing it with
counter() in a pseudo-element turns the interpolated value into visible digits, with no
script and no layout thrash.
The CSS only output does exactly that. It works in every current browser, but there are two
limits worth knowing. counter() prints plain integers, so there are no thousands separators
and no decimals; and because the digits live in ::after, they are not part of the text
content, so add an aria-label with the final figure if the number matters to screen-reader
users. For a number you want formatted as 12,500 or 1.2M, switch to the JavaScript
output, which reads the start, end and duration from data attributes, eases with the same curve
you chose here and formats with toLocaleString, so it follows the visitor's locale.
Ease out is almost always right for a counter: it races through the early hundreds and slows into the final figure, so the eye arrives at the number as it settles. Linear looks mechanical and, for large ranges, makes the last few digits a blur until the very end. Keep the duration between one and three seconds; longer than that and people stop waiting for it.
Both versions start as soon as the element is styled or the script runs. On a real page you
usually want the count to begin when the strip scrolls into view, which is a one-line
IntersectionObserver that adds a class or calls the function; the scroll animation previewer
linked below shows the pattern.
FAQ
Why does the CSS version show no commas?
counter() prints a plain integer. For 12,500 or 1.2M use the JavaScript output, which
formats with toLocaleString in the visitor's locale, so a French visitor sees a space and a
German visitor a full stop as the thousands separator.
How do I start the count when it scrolls into view?
Wrap the animation in a class and add that class from an IntersectionObserver callback, or
call the JavaScript function from the same place. The
scroll animation previewer generates that observer.
Can it count down?
Yes. Set the start higher than the end and it runs downwards, in both outputs. The easing applies the same way, so an ease-out countdown slows as it approaches the final value.
Which browsers support the CSS-only counter?
Every current version of Chrome, Edge, Safari and Firefox, since @property landed in
Firefox 128. Older browsers show the final number straight away rather than animating, which
is a safe fallback.
See also: all Shadows & Motion tools, Layout & Spacing, Shapes & SVG, UI Components, Forms & Inputs, Colour.
Related tools
Keyframe Timeline
Edit a multi-stop keyframe timeline and export the CSS.
Easing Comparison
Run two CSS easings side by side and copy the winner.
Logo Reveal
Animate a wordmark reveal and copy the CSS.
Text Animation
Animate a headline letter by letter and copy the CSS.
Confetti Generator
Fire a burst of confetti from a button, no library.