axi0motion

Odometer

Every digit rolls on its own wheel to each new value, on raised digit tiles, in the page's locale with separators and currency.

  • enhancer
  • number
  • counter
  • digits
  • roll
  • stats
  • since 0.2

Background Studio: tune it below, then copy the code

Your system asks for reduced motion: the demo shows its final state and nothing moves.

Live demo

Odometer example

Downloads this year

1,284,930

Controls

0 ms
1
-1
1100 ms

Code

It follows the controls above: change an option and the code changes with it.

<script src="https://search.axi0.io/axi0/motion/motion.js" defer></script>

<div><p class="m-demo-note">Downloads this year</p><p class="m-demo-num" data-motion="odometer" data-motion-every="2200" data-motion-step="1287">1,284,930</p></div>

The wrappers: Odometer.tsx (React, TypeScript) and Odometer.vue (Vue). Both render the same attributes as the HTML; the loader does the rest.

Options

AttributeDefaultWhat it does
data-motion-valueautoValue to show (empty reads the page's number)
data-motion-every0Add the step this often (0 = never)
data-motion-step1Step
data-motion-decimals-1Decimals (-1 keeps the page's)
data-motion-currencyautoCurrency code, like USD or EUR
data-motion-localeautoLocale (empty uses the page's language)
data-motion-duration1100Roll time
data-motion-tilestrueSet each digit on its own raised tile

Accessibility

Screen readers hear the whole formatted value once (aria-label on headings, a visually hidden copy elsewhere); the wheels are aria-hidden. Without JavaScript the number reads as written. Under reduced motion the digits change in place with no roll. Only transform, opacity and paint change, so nothing around it moves. Frames run through the shared loop, which stops off screen, in hidden tabs and under reduced motion; reduced motion shows the final state with no movement.

Size

odometer.js is 2.1 KB gzip, with text-kit.js 3.2 KB it needs. A page loads the loader (2.9 KB) and core.js (1.4 KB) once, whatever it uses.