Live Ticker
A metrics strip that scrolls forever by recycling its items, can be dragged by hand with inertia and updates with a green or red flash.
Updated
This effect is part of Effect.Labs — 840 vanilla effects, some free, some premium. Gallery has 44 effects, including 6 free. Explore the category →
3 usage examples



How it works
You write your items inside .ltk-track: one .ltk-item per metric, with a .ltk-label, a .ltk-value and, if you want a change badge, the data-delta attribute (the script builds the green, red or neutral “▲ +4.20%” pill). The script adds the separators, then hidden copies of the list until the track covers the band width plus twice the widest item: the band stays full even in a 1,700 px area.
The track moves left at 60 px/s (based on elapsed time). As soon as an item has fully left on the left, it is moved to the end of the track and the offset is corrected by its width, measured at that moment: no jump, even if a value changed length in between. Dragged to the right, the track does the opposite and brings the last item back to the front.
Hovering the band, keyboard focus inside the band or the Pause button stops the scrolling. You can grab the band with a mouse or a finger; on release it keeps the gesture's momentum, then returns to its speed. Each root exposes root.ltkTicker: push({label, value, delta}) updates every copy of a metric with a 0.55 s flash (or adds it if missing), pause(), play() and setSpeed(px). The bundled frame (header and three cards) is plain HTML dressing, with no script.
Accessibility
- No looping announcements: the band has the
marqueerole and anaria-label, withoutaria-live; updates are not read out automatically. Only your original items are read: copies carryaria-hidden="true", their linkstabindex="-1". - Pause: hover, keyboard focus on a link in the band or the Pause button (
aria-pressed) stop the scrolling (WCAG 2.2.2). - Reduced motion: under
prefers-reduced-motion: reduce, no copies, no motion, no flash; the track becomes a list you scroll with a finger, the wheel or the keyboard (tabindex="0"when it overflows).push()still updates the values. - Links: a drag longer than 5 px does not open the link under the pointer; a plain click does.
touch-action: pan-ylets the page scroll under a finger.
Browser compatibility
Pointer Events with setPointerCapture, IntersectionObserver and ResizeObserver (feature-tested), mask-image for the edge fade. Measured on 2026-11-08 in Chromium, Firefox and Playwright's WebKit: 60 px/s, stop on hover, focus and button, two independent copies, full band at 1,700 px, reduced motion, finger drag at 390 px.
Without JavaScript, the list shows still, with no separators or change pills. Without mask-image, two gradients laid on the edges take over.
The code
HTML structure to paste into your page (the CSS + JS come with your purchase):
<div class="fx-0834-root" data-ltk-speed="60" data-ltk-unit="%" data-ltk-decimals="2">
<div class="ltk-demo-panel">
<div class="ltk-panel-header">
<span class="ltk-panel-title">…</span>
<button class="ltk-btn-pause" type="button" aria-label="…" aria-pressed="false">⏸</button>
</div>
<div class="ltk-root" role="marquee" aria-label="…">
<div class="ltk-track">
<span class="ltk-item" data-delta="4.2"><span class="ltk-label">…</span><span class="ltk-value">…</span></span>
</div>
</div>
<div class="ltk-panel-stats">
<div class="ltk-stat-card">…</div>
</div>
</div>
</div>
One-time payment, no subscription — the code is yours forever
Customize
Options passed to the API or data-* attributes:
| Option / property | Default | Effect |
|---|---|---|
Items (HTML — .ltk-item inside .ltk-track) |
8 made-up shop metrics | One .ltk-label and one .ltk-value per item; a link or an icon can go inside. |
Change (HTML — data-delta on .ltk-item) |
Absent: no pill | Positive number (green ▲), negative (red ▼) or 0 (grey —). |
Unit and decimals (HTML — data-ltk-unit, data-ltk-decimals on the root) |
“%” and 2 | E.g. data-ltk-unit=" pt" data-ltk-decimals="0" shows “▲ +2 pt”. |
Speed (HTML — data-ltk-speed) |
60 (px/s) | From 0 to 600; change it later with root.ltkTicker.setSpeed(px). |
Update (JS — root.ltkTicker.push({label, value, delta})) |
No automatic update | Finds the item by its data-label (taken from the label text if missing), changes the value and the pill with a flash; adds the item if it is new. |
Dressing (HTML — .ltk-demo-panel, .ltk-panel-header, .ltk-panel-stats) |
“Shop · Today” header and three cards | Purely decorative: remove it to keep only .ltk-root and the Pause button in the root. |
Colors (CSS — .ltk-label, .ltk-value, .ltk-delta--up / --down) |
#9696aa, #d4d4d8, #4ade80 / #f87171 | Label, value and pill colors; band background on .ltk-root (#0d0d14). |
FAQ
push() calls, for instance after a request to your own server.document.querySelector('.fx-0834-root')) and, in your setInterval, call root.ltkTicker.push({label: 'Orders', value: '318', delta: 1.9}). The label must match the data-label or the .ltk-label text.