CountUp.js Guide: Animated Number Counter Options & Examples
It works well for stats sections, dashboard metrics, pricing counters, progress numbers, and scroll-triggered KPI blocks.
The package supports ESM imports, a UMD browser build, TypeScript declarations, custom formatting, callbacks, and animation plugins.
npm install countup.js
import { CountUp } from 'countup.js';
// Create a counter for the element with id="monthly-revenue".
const revenueCounter = new CountUp('monthly-revenue', 48500, {
prefix: '$',
separator: ',',
duration: 2.4
});
// Start the animation after CountUp validates the target element.
if (!revenueCounter.error) {
revenueCounter.start();
} else {
console.error(revenueCounter.error);
}
<div id="active-users">0</div>
<script src="dist/countUp.umd.js"></script>
<script>
// The UMD build exposes CountUp on the countUp namespace.
const usersCounter = new countUp.CountUp('active-users', 12750, {
separator: ',',
suffix: ' users'
});
// Start the counter after the instance passes validation.
if (!usersCounter.error) {
usersCounter.start();
}
</script>
<div id="orders-counter">0</div> <script src="./main.js" type="module"></script>
import { CountUp } from './js/countUp.min.js';
window.addEventListener('load', function() {
// Count from 0 to the final order count.
const ordersCounter = new CountUp('orders-counter', 3200, {
separator: ','
});
// Start after the page finishes loading.
ordersCounter.start();
});
Module scripts need a local server in many browsers. A direct file path can trigger a CORS error when the browser loads type="module" scripts from disk.
<div id="remaining-seats">120</div>
import { CountUp } from 'countup.js';
// Count down from 120 to 35.
const seatsCounter = new CountUp('remaining-seats', 35, {
startVal: 120,
duration: 1.8
});
seatsCounter.start();
<div id="conversion-rate">0</div>
import { CountUp } from 'countup.js';
// Show one decimal place and append a percent sign.
const rateCounter = new CountUp('conversion-rate', 18.7, {
decimalPlaces: 1,
decimal: '.',
suffix: '%',
duration: 2
});
rateCounter.start();
<section class="stats-panel"> <span id="completed-projects">0</span> </section>
import { CountUp } from 'countup.js';
// autoAnimate starts the counter when the target becomes visible.
const projectCounter = new CountUp('completed-projects', 860, {
autoAnimate: true,
autoAnimateDelay: 150,
autoAnimateOnce: true
});
// Do not call start() when autoAnimate controls the animation.
if (projectCounter.error) {
console.error(projectCounter.error);
}
autoAnimate uses IntersectionObserver in current releases. Older CountUp.js versions used enableScrollSpy, scrollSpyDelay, and scrollSpyOnce. Those names now exist as deprecated options.
.stats-panel span {
font-variant-numeric: tabular-nums;
}
font-variant-numeric: tabular-nums helps counters look steadier in fonts that use variable-width digits.
startVal (number): Sets the number where the animation begins. Default: 0.decimalPlaces (number): Sets the number of digits after the decimal point. Default: 0.duration (number): Sets the animation length in seconds. Default: 2.useGrouping (boolean): Adds grouping separators to large numbers. Default: true.useIndianSeparators (boolean): Uses Indian-style number grouping. Default: false.useEasing (boolean): Applies easing to the counter animation. Default: true.smartEasingThreshold (number): Sets the value threshold where smart easing begins. Default: 999.smartEasingAmount (number): Sets the eased amount for values above the smart easing threshold. Default: 333.separator (string): Sets the grouping separator character. Default: ','.decimal (string): Sets the decimal character. Default: '.'.easingFn (function): Sets a custom easing function.formattingFn (function): Sets a custom formatter for the rendered value.prefix (string): Adds text before the number. Default: ''.suffix (string): Adds text after the number. Default: ''.numerals (string[]): Replaces the default digits with custom numeral glyphs.onCompleteCallback (function): Runs after the animation completes.onStartCallback (function): Runs when the animation starts.plugin (CountUpPlugin): Uses a custom renderer for alternate animation styles.autoAnimate (boolean): Starts the animation when the target becomes visible. Default: false.autoAnimateDelay (number): Sets the delay in milliseconds after auto animation triggers. Default: 200.autoAnimateOnce (boolean): Runs auto animation only once. Default: false.enableScrollSpy (boolean): Deprecated. Use autoAnimate.scrollSpyDelay (number): Deprecated. Use autoAnimateDelay.scrollSpyOnce (boolean): Deprecated. Use autoAnimateOnce.// Starts the counter animation.
salesCounter.start();
// Starts the animation and runs a callback after completion.
salesCounter.start(function() {
console.log('Revenue counter finished.');
});
// Pauses the active animation or resumes a paused animation.
salesCounter.pauseResume();
// Resets the counter to its starting value.
salesCounter.reset();
// Updates the end value and animates to the new number.
salesCounter.update(72500);
// Cancels animation work and clears observers and callbacks.
salesCounter.onDestroy();
CountUp.js does not provide a named event system. Use onStartCallback, onCompleteCallback, or the callback argument passed to start() when you need lifecycle hooks.
import { CountUp } from 'countup.js';
const signupCounter = new CountUp('signup-count', 2400, {
// Runs when the animation starts.
onStartCallback: function() {
console.log('Signup counter started.');
},
// Runs after the animation completes.
onCompleteCallback: function() {
console.log('Signup counter completed.');
}
});
signupCounter.start();
CountUp.js supports custom animation plugins. A plugin provides a render() method that receives the target element and the formatted value for each frame.
import { CountUp } from 'countup.js';
import { Odometer } from 'odometer_countup';
// Use the Odometer plugin for a rolling digit effect.
const inventoryCounter = new CountUp('inventory-total', 99999, {
plugin: new Odometer({
duration: 2.3,
lastDigitDelay: 0
}),
duration: 3
});
inventoryCounter.start();
Q: What is CountUp.js used for?
A: CountUp.js animates numeric values for stats blocks, dashboards, pricing counters, and scroll-triggered KPI sections.
Q: Can CountUp.js count down?
A: Yes. Set a higher startVal and a lower end value.
Q: Does CountUp.js support TypeScript?
A: Yes. The npm package includes TypeScript declaration files.
Q: How do I start CountUp.js when the element appears on screen?
A: Set autoAnimate: true and create the instance. Do not call start() for that counter.
Q: Why does my module import fail from a local HTML file?
A: Browser module scripts often need a local server. Run the page through a local development server.
Q: What replaced enableScrollSpy?
A: Use autoAnimate. Use autoAnimateDelay and autoAnimateOnce for the matching delay and once-only behavior.
05/08/2026
v2.10.0 (06/02/2025)
v2.9.0 (06/02/2025)
v2.8.1 (04/23/2025)
v2.8.0 (08/26/2023)
v2.7.0 (06/29/2023)
v2.6.2 (05/01/2023)
v2.6.1 (05/01/2023)
v2.6.0 (03/13/2023)
v2.5.0 (03/01/2023)
v2.4.2 (01/29/2023)
v2.4.1 (01/25/2023)
v2.3.2 (07/10/2022)
v2.3.1 (06/29/2022)
v2.3.0 (06/28/2022)
v2.2.0 (05/18/2022)
v2.1.0 (03/03/2022)
v2.0.8 (07/28/2020)
v2.0.7 (08/26/2020)
v2.0.6 (08/08/2020)
v2.0.4 (06/20/2019)
v1.9.3 (09/21/2018)
The post CountUp.js Guide: Animated Number Counter Options & Examples appeared first on CSS Script.
May 10, 2026 Imagine if the biggest, most influential businesses in this country came together…
Crimson Desert developer Pearl Abyss has released this week’s update as promised, and it adds…
It took nearly 50 years. WKRP in Cincinnati is no longer just a TV sitcom.…
The Mountain Home Area Chamber of Commerce hosted its 2026 Four-Person Scramble Golf Tournament Friday…
Growing up and spending all of his 44-years in Lead Hill and living on the…
Mountain Home Mayor Hillrey Adams says work is continuing at a rapid pace as the…
This website uses cookies.