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
Downloads this year
1,284,930
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>
import { Odometer } from "./motion/react/Odometer";
<Odometer>Your content</Odometer>
<script setup lang="ts">
import Odometer from "./motion/vue/Odometer.vue";
</script>
<template>
<Odometer>Your content</Odometer>
</template>
const el = document.querySelector("#title");
el.dataset.motion = "odometer";
// run the entrance again: axi0Motion.play(el, "odometer")
The wrappers: Odometer.tsx (React, TypeScript) and Odometer.vue (Vue). Both render the same attributes as the HTML; the loader does the rest.
Options
| Attribute | Default | What it does |
|---|---|---|
data-motion-value | auto | Value to show (empty reads the page's number) |
data-motion-every | 0 | Add the step this often (0 = never) |
data-motion-step | 1 | Step |
data-motion-decimals | -1 | Decimals (-1 keeps the page's) |
data-motion-currency | auto | Currency code, like USD or EUR |
data-motion-locale | auto | Locale (empty uses the page's language) |
data-motion-duration | 1100 | Roll time |
data-motion-tiles | true | Set 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.