Count Up
A free count up text effect for stats and metrics, built on GSAP.
- Automated axe check
- Reduced-motion tested
- SSR build verified
- GSAP
- 2 runtime packages
Count Up is a free text effect component for Next.js and React that animates a number from zero to its final value with GSAP. The count starts once when the wrapper scrolls into view, runs over the library's 1.2 second motion beat with an expo ease, and is styled with Tailwind.
The final formatted value, including prefix, suffix and Intl.NumberFormat grouping, is rendered in the server HTML, so crawlers, no-JS visitors and reduced-motion users always read the real number. The wrapper carries an aria-label with the final value while the mutating node is hidden from assistive technology, and tabular numerals keep the width constant during the count, so layout never shifts.
Template Empire
Components installed
Uptime last quarter
Revenue attributed
Each stat counts up from zero the moment it scrolls into view, then settles on the real number. Enable reduced motion and the finished figures are simply here.
Install
Add the @te registry to your components.json once:
{
"registries": {
"@te": "https://templateempire.io/r/{name}.json"
}
}Then install the component:
npx shadcn@latest add @te/text-counterUsage
import { TextCounter } from "@/components/text-counter";
export function Example() {
return (
<p className="text-5xl font-semibold">
<TextCounter value={12847} suffix="+" /> components installed
</p>
);
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
| value | number | required | Final value; rendered formatted in the SSR HTML. |
| duration | number | 1.2 | Count duration in seconds (--dur-4). |
| decimals | number | 0 | Fraction digits in the formatted output. |
| prefix | string | "" | Rendered before the number (e.g. "$"). |
| suffix | string | "" | Rendered after the number (e.g. "+", "%"). |
| locale | string | "en-US" | Fixed Intl.NumberFormat locale so SSR and client formatting match. |
| as | ElementType | "span" | Element rendered as the wrapper. |
| className | string | undefined | Additional classes merged onto the wrapper. |
Customisation
Count Up deliberately ships without component-level CSS variables. Formatting is controlled entirely through props: decimals, prefix and suffix shape the output, the fixed locale sets grouping and decimal separators, and duration paces the count against your motion system:
<TextCounter
value={99.98}
decimals={2}
suffix="%"
locale="de-DE"
duration={2}
/>Frequently asked questions
- Is Count Up free for commercial use?
- Yes. Count Up is MIT licensed, so you can use it in personal and commercial projects without attribution.
- Does Count Up cause layout shift or hurt SEO?
- No. The server HTML contains the final formatted value, so crawlers index the real number and nothing depends on JavaScript. During the count the number is set in tabular numerals, so every digit occupies the same width and the element never changes size. With reduced motion enabled the final value renders immediately with no counting.
- How do I format the number as a currency or percentage?
- Use the prefix and suffix props for symbols, the decimals prop for fraction digits, and the locale prop for grouping and decimal separators. The locale is fixed rather than read from the browser, so server and client output always match.