React Counting Number
React counting number component with spring animations. TypeScript counters with in-view detection and decimal support for Next.js apps using shadcn/ui.
Powered by
Trying to implement text animations?
Join our Discord community for help from other developers.
Ever watched a number count up from 0 to 10,000 and it takes forever? Or worse, it counts so fast it looks like a slot machine having a seizure? Yeah, most counting animations are garbage. This component actually gets the timing right with spring physics instead of linear interpolation nonsense.
Smooth number animations
Count up to any number with spring-based animations that feel natural:
Built with TypeScript and shadcn/ui, so it works with your existing React setup and Next.js applications. Spring animations handle the physics, in-view detection prevents wasted CPU cycles, and the whole thing runs at 60fps without re-renders in modern JavaScript frameworks.
Installation
npx shadcn@latest add https://www.shadcn.io/registry/counting-number.json
npx shadcn@latest add https://www.shadcn.io/registry/counting-number.json
pnpm dlx shadcn@latest add https://www.shadcn.io/registry/counting-number.json
bunx shadcn@latest add https://www.shadcn.io/registry/counting-number.json
Usage
import { CountingNumber } from "@/components/text/counting-number";
<CountingNumber
number={42069}
inView={true}
transition={{ stiffness: 100, damping: 30 }}
/>;
Why most counting animations suck
Most developers either use setInterval
with linear increments (looks robotic) or CSS transitions (can't handle dynamic values) in their React components. Neither approach feels natural because real-world motion doesn't work that way in JavaScript applications.
This React component uses Motion's spring physics with full TypeScript support. Springs naturally accelerate and decelerate, creating that satisfying "snap" when the number settles. The default stiffness (90) and damping (50) values took actual testing to get right—not just random numbers that "looked okay" in Next.js projects.
Plus, most counters start animating immediately on page load. Users never see them. This component waits until it's actually visible using Intersection Observer. Save those CPU cycles for something useful in modern JavaScript development.
Examples
Decimal numbers with custom separators
International formatting with proper decimal handling:
Countdown animations
Start from a high number and count down for timers or countdowns:
Features
- Spring physics that actually feel natural (not linear garbage) in React applications
- In-view detection so animations don't waste CPU before users see them
- Decimal support with international formatting for JavaScript projects
- Padding for consistent widths (no layout shift when counting) in Next.js
- Complete TypeScript support with full type definitions and IntelliSense
- 60fps performance using Motion values (no React re-renders)
- Works seamlessly with shadcn/ui components and free open source integration
API Reference
CountingNumber
Animated number display with spring transitions.
Prop | Type | Default | Description |
---|---|---|---|
number | number | required | Target number to count to |
fromNumber | number | 0 | Starting number for animation |
decimalPlaces | number | 0 | Decimal places to display |
decimalSeparator | string | "." | Character for decimals |
padStart | boolean | false | Add leading zeros |
inView | boolean | false | Only animate when visible |
inViewMargin | string | "0px" | Viewport margin for trigger |
inViewOnce | boolean | true | Animate only once |
transition | SpringOptions | { stiffness: 90, damping: 50 } | Spring configuration |
className | string | - | Additional CSS classes |
...props | HTMLAttributes<HTMLSpanElement> | - | Standard span attributes |
Spring Configuration
Motion spring physics for natural animations:
Property | Range | Effect |
---|---|---|
stiffness | 1-1000 | Higher = faster animation |
damping | 1-100 | Higher = less bounce |
mass | 0.1-10 | Higher = more inertia |
Common gotchas
Numbers jumping on mount: Always set inView={true}
unless you want immediate animation in React applications. Otherwise the component animates before users scroll to it.
Decimal formatting breaks: The decimalSeparator
prop only affects display, not parsing in this TypeScript component. Your number
prop should always use standard JavaScript number format (period for decimals).
Layout shift during counting: Use padStart={true}
or set a fixed width on the container in Next.js projects. Otherwise the element width changes as digits increase.
Animation feels sluggish: Default springs work for most React applications. For snappier animations, increase stiffness to 150-200. For smoother, reduce damping to 20-30 in JavaScript implementations.
Memory leaks with rapid updates: This React component handles cleanup automatically, but avoid changing the number
prop in tight loops. Debounce your updates if needed.
Related text components you will also like
Sliding Number
Mechanical counter-style digit sliding with tabular fonts
Rolling Text
3D character rolling with realistic physics and perspective
Text Generate Effect
Progressive character generation with realistic typing timing
Typing Text
Realistic typewriter effects with human-speed timing and cursor blinking
Splitting Text
Character, word, or line splitting with perfect timing
Shimmering Text
Wave-like shimmer effects that flow naturally across text
Questions developers actually ask
React Container Text Flip
Animated text container with word cycling and dynamic width. Perfect for React applications requiring smooth text transitions with TypeScript support.
React Curved Loop Text
Interactive curved text animation that follows an SVG path with drag controls and smooth scrolling effects. Perfect for dynamic marquees.