# Odometer Reel Stats

> A stats section where a sideways strip of action photographs rolls one giant odometer figure, reel by reel, as visitors swipe, drag or jump between results.

Canonical: https://gsapvault.com/sections/odometer-reel-stats-section
Live demo: https://gsapvault.com/demos/odometer-reel-stats-section/index.html

| Property | Value |
|----------|-------|
| Type | section |
| Tier | paid |
| Price | Included only in the Vault |
| Difficulty | advanced |
| Plugins | Core GSAP only |
| Techniques | odometer-counter, horizontal-scroll, snap, drag, momentum, velocity-reactive, interruptible-transitions, progressive-enhancement, keyboard-navigation, container-queries, responsive-section |
| Uses Lenis | No |

## Overview

Odometer Reel Stats Section shows what an organisation or product has achieved, one figure at a time, and ties each figure to a photograph, a plain-English explanation and a timeframe. On a signal-orange ground, a single giant condensed figure sits beside its explanation, above a full-bleed strip of action photographs that scrolls sideways.

The strip drives the figure. As visitors swipe, drag or scroll the photographs, every digit of the figure is a reel that rolls continuously towards the next result: the units spin fastest, like a real odometer, leading digits fold away when the next figure is shorter, and a directional blur and lean follow how fast the strip is moving. Stop halfway and the reels stop halfway; reverse and they roll back exactly. A lane of split buttons below jumps to any figure by pointer, touch or keyboard.

The fictional Swiftline Run Club example reports a first season in five figures with five generated photographs of its runs. The figures are an ordinary ordered list: without JavaScript, each photograph shows with its own figure and copy in a sideways-scrolling strip, and screen readers always read the final figures from that list.

## Features

- One giant figure whose digits are rolling reels, scrubbed continuously by the photo strip's scroll position
- Odometer behaviour: units spin fastest, leading digits and group separators fold away, prefixes and suffixes crossfade
- Speed-linked directional blur and lean on the figure, and a slight lean on the photographs, that settle when the strip stops
- Native sideways scrolling with snapping for touch and trackpads, plus mouse drag with a flick that carries on to the next figure
- Split lane of numbered buttons with a progress fill that tracks the strip exactly
- Arrow keys, Home and End on the focused strip; repeated presses mid-move step on from the figure being approached
- Readout of label, explanation and timeframe that changes with direction-aware motion and never shifts the layout
- First figure rolls up from zero when the section arrives; screen readers only ever get the final values
- Figures, counts, split labels and reel widths derived from the markup; the figure is fitted to its column
- Reduced-motion, no-JavaScript and missing-GSAP fallbacks, independent instances and exact teardown

## Use Cases

- Sports clubs, events and charities reporting a season or campaign in numbers
- Product launches showing adoption, distance, time saved or other results with the photograph behind each
- Studios and agencies presenting results for a case study
- Annual reviews and impact pages that need each figure explained in plain English

## Vibe-Code Ready Setup

This website section includes `START-HERE-AI.md`, a product-specific copy-paste setup prompt for Cursor, Claude Code, ChatGPT, GitHub Copilot, Windsurf, and other coding assistants. It tells the assistant to inspect the existing stack, integrate the supplied files, preserve the design, scope selectors, retain accessibility and responsive behaviour, add framework-appropriate GSAP cleanup, and report what it tested.

[How AI-assisted setup works](https://gsapvault.com/vibe-coding)

## How It Works

Each figure is a list item with its photograph, value, label, explanation and timeframe. The script reads those values, builds one reel per digit position (each a strip of 0 to 9) and measures the digit, separator and affix widths in the chosen face so it can fit the figure to its column.

The photo strip is an ordinary horizontal scroller with CSS scroll snapping. Its scroll position is mapped to a fractional progress between the snap points of neighbouring items, and every frame each reel is positioned between its digit in the current figure and its digit in the next, with extra full turns on the lower digits. Digits and separators that exist in only one of the two figures shrink and fade in step, so the figure changes length smoothly. Because the figure is a pure function of scroll position, interruption and reversal are exact.

Buttons, keys and mouse flicks move the strip with a GSAP tween on scrollLeft, with snapping suspended during the move and restored at the end; any wheel, touch or new drag cancels a move in progress. A quickTo on the scroll velocity drives an SVG directional blur and a skew that decay to nothing when the strip stops. The section never installs a scroller or captures vertical wheel input, so the host page keeps its scroll.

## Documentation

How this website section works and how it goes into a page. The reference you use once you own the files (worked examples, events, the programmatic API, the class list) ships with the download.

### Quick Start

1. Copy `assets/style.css`, `assets/script.js` and `assets/img/` into your project.
2. Load the fonts, the stylesheet, GSAP and the script:

_Code snippet omitted: it ships with the download._

3. Copy the whole `<section class="ors" data-odometer-stats>` element from `index.html`, between the `EXTRACT START` and `EXTRACT END` comments. Everything else in `index.html` is demo page furniture.

The script mounts every `[data-odometer-stats]` on the page. It needs GSAP core only; no plugins.

### Make it yours

#### Figures

Each figure is one list item inside `<ol data-ors-list>`:

_Code snippet omitted: it ships with the download._

- **The value** is the text of `data-ors-value`. Use whole numbers; group separators such as `46,812` or `46.812` are kept and fold away on shorter figures.
- **A prefix or suffix** goes in its own span beside the value: `<span class="ors-item__prefix" data-ors-prefix>£</span>` before it, or `<span class="ors-item__suffix" data-ors-suffix>%</span>` after it.
- **The label** says what is counted; the body says why it matters; the timeframe says when. Keep them all: they are what make a figure mean something.
- **`data-ors-split`** is the short name on the figure's button under the strip. On phones only the number shows.
- **Add, remove or reorder** whole `<li>` elements. The reels, buttons, `01 / 05` counters and the figure's size all follow the markup. With a single item the section shows one static figure and no buttons.
- The first two images use `loading="eager"`; later ones can stay `lazy`, because the script loads them all once the page has loaded.

Screen readers read each item's own copy, so they always hear the final figure, never a rolling one. The large rolling figure and the readout beside it are hidden from assistive technology.

#### Photographs

| File | Shows | Size |
| --- | --- | --- |
| `assets/img/distance.webp` | Runners crossing a footbridge at dusk | 1536 x 1024 |
| `assets/img/first-finish.webp` | A first-time finisher breaking the tape | 1536 x 1024 |
| `assets/img/every-saturday.webp` | Runners in heavy rain | 1536 x 1024 |
| `assets/img/came-back.webp` | Two runners high-fiving | 1536 x 1024 |
| `assets/img/free.webp` | A group setting off before dawn | 1536 x 1024 |

To replace one, put your photo in `assets/img/`, change the `src`, the `width` and `height` to its real pixel size, and the `alt` text. Any aspect ratio works: the frame is 16:10 on wide screens and 4:5 on phones (set by `--ors-slide-ratio`), and the photo is cropped to fill it. Move the crop with `--ors-focus` on the `<figure>` (for example `30% 50%` keeps the left side). Around 1600px wide is plenty. Keep the main subject near the middle: the photos drift slightly sideways as the strip moves.

#### Brand variables

All on the section root, `.ors`:

_Code snippet omitted: it ships with the download._

A rebrand, for example a cycling event on lime:

_Code snippet omitted: it ships with the download._

Check the contrast of `--ors-ink` on `--ors-ground` (the demo pair is 6.05:1). The figure is fitted to its column from real glyph measurements, so any display face works; choose one with lining figures. The Anybody width axis is what gives the narrow figures and wide titles: with another face, remove the `font-stretch` and `font-variation-settings` lines or leave them, since faces without a width axis ignore them.

### Behaviour and options

- **Strip:** a native sideways scroller with snapping. Touch and trackpads scroll it directly; a mouse can drag it and flick it on to the next figure. Vertical wheel movement always scrolls the page.
- **Figure:** follows the strip's exact position, so stopping halfway leaves the reels halfway and reversing rolls them back. Its blur and lean follow the strip's speed and settle to nothing.
- **Buttons and keys:** the buttons under the strip jump to a figure. With the strip focused, Left and Right (or Page Up and Page Down) step, Home and End go to the ends. A new press mid-move re-targets; any wheel, touch or drag cancels a move.
- **Intro:** when the section scrolls into view, the first figure rolls up from zero. Set its length in seconds with `data-intro-duration="1.8"` on the root.

JavaScript API:

_Code snippet omitted: it ships with the download._

Instances are independent; several can share a page.

### Accessibility and integration

- The heading is an `<h2>`; each figure's label is an `<h3>`. Change the tags freely: styling uses classes.
- The strip is a labelled, focusable region; the buttons expose the current figure with `aria-current` and include its value in their names, and moves by button or key are announced politely.
- With `prefers-reduced-motion: reduce`, there is no intro, blur, lean or parallax, the figure changes whole, and buttons jump without animation. Changing the preference while the page is open is handled.
- Without JavaScript, or if GSAP fails to load, the section is a sideways-scrolling strip with a visible scrollbar in which every photograph carries its own figure, label, explanation and timeframe.
- The section is full width by design and adapts to narrow columns with container queries. It does not pin, install a smooth scroller or change the page's scroll behaviour.
- The "Find your first run" link points at `#find-a-run`: replace it with your own destination.

### Dependencies and credits

- [GSAP 3.15.0](https://gsap.com) core from jsDelivr, under the [GSAP standard licence](https://gsap.com/standard-license/).
- [Anybody](https://fonts.google.com/specimen/Anybody), [Geist](https://fonts.google.com/specimen/Geist) and [Geist Mono](https://fonts.google.com/specimen/Geist+Mono) from Google Fonts, under the SIL Open Font License.
- The five photographs are generated concept images of fictional people, made for this section; they do not show a real club or event. Swiftline Run Club and every figure, date and claim in the demo are sample content: replace them with your own before publishing.

## What You Get

- `index.html`: working demo page
- `assets/script.js`: commented, readable source
- `assets/style.css`: effect styles
- `README.md`: full documentation with examples and framework integration notes
- `START-HERE-AI.md`: product-specific copy-paste prompt for AI-assisted setup
- `LICENSE.txt`: standard license terms
- Lifetime updates: re-download anytime from your library

## Get the Code

This website section is included only in the Vault, for existing and new owners. It is not sold individually. The standard licence covers unlimited personal and commercial projects; bundled assets retain their own licence requirements.

- [Get the Vault](https://gsapvault.com/pricing)
- [The Vault (£99 one-time, best value): every collection in the Vault library, plus future items added to those collections](https://gsapvault.com/effects)

---

From [GSAP Vault](https://gsapvault.com): production-ready GSAP animation effects. Full catalog for agents: https://gsapvault.com/llms-full.txt
