← Back to Blog

Building a Number Flow Animation

A step-by-step guide to animating numeric values digit-by-digit with direction-aware motion, tabular alignment, and accessibility in mind.

Eduardo CalvoEduardo Calvo
··1 min read

In this tutorial, we'll build a Number Flow animation step by step. Use the + / − buttons in the preview to trigger the animation as each layer is added.

Static Number

Start by rendering a number with tabular-nums so digits stay aligned.

<span className="tabular-nums">{value}</span>

Split into Digits

Convert the value to a string and animate each character independently.

const digits = value.toString().split("");<span className="tabular-nums">  {digits.map((d, i) => <span key={i}>{d}</span>)}</span>

Animate Per Digit

Use AnimatePresence keyed by the character so each digit can enter and exit.

<AnimatePresence mode="popLayout" initial={false}>  <motion.span    key={digit + index}    initial={{ y: 12, opacity: 0 }}    animate={{ y: 0, opacity: 1 }}    exit={{ y: -12, opacity: 0 }}  >    {digit}  </motion.span></AnimatePresence>

Direction-Aware

Slide up when the value increases, slide down when it decreases.

const direction = value > previous ? 1 : -1;initial={{ y: 12 * direction, opacity: 0 }}exit={{ y: -12 * direction, opacity: 0 }}

Spring Timing

A quick spring with low bounce keeps the motion crisp.

transition={{  type: "spring",  duration: 0.3,  bounce: 0.1,}}

Reduced Motion

Fall back to an instant swap when users prefer less motion.

const shouldReduceMotion = useReducedMotion();transition={shouldReduceMotion  ? { duration: 0 }  : { type: "spring", duration: 0.3, bounce: 0.1 }}
Live PreviewStep 1/6
$100

Key Takeaways

After building this component, you've learned:

  1. tabular-nums keeps digits at a fixed width — essential for any animated counter
  2. Split by character so digits can enter and exit independently
  3. AnimatePresence with mode="popLayout" lets old and new digits coexist during transition
  4. Direction-aware motion (sliding up vs. down) makes increments and decrements feel different
  5. Springs with low bounce read as "mechanical" — perfect for numbers and counters
  6. Reduced motion swaps instantly — the number still updates, just without the slide

Install the Component

npx smoothui-cli add number-flow

Check out the full documentation for all props and variations.

Share:

More Posts