Media & time

Animated counter

A number that counts up to its value the first time it is scrolled into view.

Client componentSource

Import

import { AnimatedCounter } from '@the_viveksingh/vivek-ui'

Count up on scroll

Starts when it enters the viewport. Under prefers-reduced-motion it renders the final number immediately rather than animating.

83

Counts up when it scrolls into view. With reduced motion requested it renders the final number immediately instead of animating.

<Heading level={3} size="hero">
  <AnimatedCounter value={83} duration={1200} />
</Heading>

Formatted

format takes Intl.NumberFormat options, or your own function. Currency, percentages and fixed decimals all come from the platform rather than string maths.

₹4,280

99.98%

~1,268 tests

<AnimatedCounter
  value={4280}
  format={{ style: 'currency', currency: 'INR', maximumFractionDigits: 0 }}
  locale="en-IN"
/>

<AnimatedCounter value={99.98} suffix="%" format={{ minimumFractionDigits: 2 }} />
<AnimatedCounter value={1268} prefix="~" suffix=" tests" />

Props

Generated from the package's own type declarations, so this table cannot drift from the code.

Props for AnimatedCounter
PropTypeDefaultDescription
valuenumberThe number to land on. Defaults to `0`.
fromnumberThe number to count from. Defaults to `0`.
durationnumberMilliseconds. Defaults to `1600`. `0` disables the animation entirely.
formatCounterFormat`Intl.NumberFormat` options, or a function.
localestring | string[]Locale for `Intl.NumberFormat`. Pass it if the page is server-rendered: the runtime default differs between Node and the browser, and that difference IS a hydration mismatch, because the final value is what both sides render.
prefixstring
suffixstring
startOnViewbooleanWait until the counter is scrolled into view. Defaults to `true`.

Every remaining prop is spread onto the root element, so all standard HTML and ARIA attributes work. className and style are merged with the library's own, never replaced, and the ref forwards to the root DOM node.

Rendering