How to Animate a Number Counter in UI
How to animate a counter correctly: keeping digits from jumping, easing to the exact value, formatting per locale, and not announcing every frame to screen readers.
Core Takeaway
A counter works when the number is the point, such as a dashboard total or a result the user just earned. Animate the value with a decelerating curve so it lands exactly on the real figure, use tabular digits so the width does not jump, and format the number for the user's locale at the end. Announce the final value once, not every frame.
When a counter helps and when it misleads
Counting up draws attention to a number, which is useful for a result the user caused. It is less useful for data that simply loaded, and it can mislead if the number is still changing. Never animate to a value you do not have. If a figure is an estimate, show it as one rather than making the motion imply precision.
Animate the value, not the layout
The number itself is text, and changing text changes width. Proportional digits make the line jitter, so use font-variant-numeric: tabular-nums, or a fixed-width container. Keep the rest of the layout still while the digits change.
Ease out, land exactly
A counter should slow as it approaches the target, then stop on the real value. Linear counting looks mechanical; overshooting and bouncing looks like a game. Use a decelerating curve and make the final frame exactly the number you intend to display.
Format for the reader
Thousands separators, decimal places and currency symbols are locale-specific. Animate the raw value, then format it on each update or at the end. Round consistently, and avoid showing a spinner of changing decimal places that never settles.
Accessibility: announce the result once
A screen reader should hear the final value, not every intermediate frame. Keep the live region quiet during the count and update it once at the end, or render the final number in the accessible label from the start. Users who prefer reduced motion should see the final value immediately.
Where ExodeUI fits
ExodeUI is a browser and desktop tool for interactive UI and animation, with state machines, spring physics, inputs and events, saved as one open .exode JSON file with runtimes for React, Vue, Svelte, Angular, Solid, React Native, SwiftUI and Flutter. A counter is simple enough to build in code, so use a tool like ExodeUI only if the same motion needs to be shared and edited across platforms.
Key Principles to Remember
- Use a counter when the number is the point, not for every value
- Tabular digits prevent the text from jittering
- Ease out and land exactly on the real figure
- Format the number for the user's locale
- Announce the final value once, not every frame
Frequently Asked Questions
Sources
- font-variant-numeric — MDN Web Docs
- ARIA live regions — MDN Web Docs
- prefers-reduced-motion — MDN Web Docs