SMALL LIBRARY. ENDLESS POSSIBILITIES.

A little motion.
A lot of possibility.

Accessible ticker tapes for the open web.
Announcements, logos, and prices. Just your content, in motion.

npm install @samline/ticker

Zero dependencies TypeScript ready MIT licensed

THE LIBRARY, LIVE
02 / BRAND STRIP SAMPLE LOGOS, NO ENDORSEMENTS.
03 / MARKET TAPE ILLUSTRATIVE DATA.
BTC $94,210.40 +2.31% ETH $3,540.18 +1.84% SOL $182.07 −0.42% AAPL $228.10 +0.62% TSLA $341.92 −1.18% NVDA $138.55 +3.07% SPY $592.40 +0.22% META $612.83 +0.91%

Ticker manages motion. Your integration should provide a pause control and keep the original content readable.

ONE SMALL SCRIPT. RIGHT AT HOME IN YOUR STACK.

JavaScript TypeScript React Vue Svelte Shopify WordPress
01 / Less code. More care.

Thoughtful by default.
Effortless by design.

Zero dependencies

No animation library, no framework peer, no transitive packages. Import only the API your project needs.

Accessible by default

Visual clones stay out of the accessibility tree and keyboard order. Honors prefers-reduced-motion automatically.

Responsive lifecycle

Remeasures on resize. Call refresh() after changing content. Pauses when the ticker leaves the viewport or the document is hidden.

Multiple entrypoints

Package imports or an HTML script tag, with the same controller API. Optional registry, page manager and core helpers fit different ownership needs.

Framework agnostic

Works in React, Vue, Svelte, Astro, plain HTML, WordPress, or Shopify. No adapter, no wrapper, no peer dependency.

Enhances your markup

Pass a selector or DOM element. Your source is restored on destroy(); the controller manages animation markup.

02 / Choose your entrypoint

Built for every runtime.

Start with the package import or an HTML script tag. The optional registry is available in either setup; CDN describes file delivery, not a different Ticker API.

Main

@samline/ticker

Package / ESM entry: import ticker() and load style.css. Also exports types, defaults and the optional registry.

Vanilla

@samline/ticker/vanilla

Element-scoped controller plus the declarative page manager. Auto-discovers tickers as the DOM changes.

Registry

@samline/ticker/browser

Optional ID-based registry for module imports. This browser subpath does not install window.Ticker and is not the CDN script.

HTML / CDN

/browser/global

Load the script from a CDN or your own server, plus style.css. It exposes window.Ticker for plain HTML, WordPress or Shopify.

Core

@samline/ticker/core

Types, defaults, state factories, and validation helpers for advanced integrations and custom builds.

Style

/style.css

Required layout, animation, and reduced-motion styles. One import, no CSS framework required.

03 / From zero to rolling

Three steps. Package or script tag.

Installed with npm, pnpm or bun? Choose Package / ESM to import Ticker. Loaded the CDN files? Choose HTML / CDN to call window.Ticker. Both return the same controller.

Understand the loading options
1

Install

terminal
npm install @samline/ticker
terminal
pnpm add @samline/ticker
terminal
bun add @samline/ticker
index.html
<link rel="stylesheet" href="https://unpkg.com/@samline/ticker@2.1.0/dist/style.css">
<script src="https://unpkg.com/@samline/ticker@2.1.0/dist/browser/global.global.js"></script>
2

Add markup

Write the content as you normally would. The library enhances it, never replaces it.

index.html
<div id="news">
  <a href="/one">First story</a>
  <a href="/two">Second story</a>
  <a href="/three">Third story</a>
</div>
3

Initialize

main.ts
import { ticker } from '@samline/ticker'
import '@samline/ticker/style.css'

const news = ticker('#news', {
  duration: 20,
  pauseOnHover: true,
})
inline script
const news = window.Ticker.ticker('#news', {
  duration: 20,
  pauseOnHover: true,
})

This is the minimal setup. Explore duration, direction and hover behavior before adapting the ticker to your design.

Explore configuration options
04 / Working with a live instance

Beyond the first render.
Handle what changes.

Changing settings, editing content and removing a registered ticker need different actions. Start with the instance from Get started, then use the recipe that fits.

Controller

Change direction without starting over

Use update() on the existing instance. Omitted settings keep their current values, so changing direction leaves the configured duration intact. The library schedules the refresh for you.

Read the update() reference
update.js
news?.update({
  direction: 'right',
})
Controller

Edit the source, then sync its copies

Add content to source, rather than the generated copies. Explicitly refresh after the edit: a resize check can reuse copies if the measured width stays unchanged.

See how content refresh works
content.js
const item = document.createElement('span')
item.textContent = 'Shipping something new.'

news?.source.append(item)
news?.refresh()
Optional registry

Remove the registration, too

If you created the ticker with window.Ticker.newTicker() in HTML / CDN, clean it up through destroyTicker(id). This removes the registry entry as well as the instance. Calling only the returned controller’s destroy() leaves registry bookkeeping behind.

Understand registry ownership
cleanup.js
window.Ticker.destroyTicker('news')
Try the complete working examples
05 / Good questions

Frequently asked questions.

Why not just use a CSS animation?
CSS handles the animation, while JavaScript manages clones, visibility, and changing measurements. This library provides that lifecycle. Call refresh() after updating content or loading fonts, and provide a pause control for continuous motion.
Does it work without a framework?
Yes. HTML / CDN loads a script that exposes window.Ticker in plain HTML, WordPress or Shopify. Serve it from a CDN or your own server. There is no build step, no peer dependency, and no window pollution beyond the Ticker namespace.
How does it handle accessibility?
Visual clones are marked aria-hidden="true" and removed from the tab order, so screen readers and keyboard users only see your original content. The library also pauses animation when the document is hidden and when the user's system reports a preference for reduced motion.
Is the native <marquee> element deprecated?
Yes — both WHATWG and the HTML living standard list <marquee> as obsolete. This library gives you the behavior people still want from a marquee, on top of a normal <div> you fully control.
Can I use it with React, Vue, or Svelte?
Yes. Pass a ref to a DOM element into the ticker() factory and call destroy() from your unmount handler. There is no framework adapter to install and no peer dependency to ship.
Does it pause when the tab is hidden?
Yes. The library listens to the document visibility API and to the IntersectionObserver for the ticker element itself, so the animation only runs when the user can actually see it. This keeps CPU and battery usage in check on long-running pages.
How big is the bundle?
Size depends on the entrypoint and your bundler’s tree shaking. The locally built v2.1.0 browser bundle is approximately 8.3 KiB gzipped, plus 0.7 KiB gzipped for the required stylesheet. There are zero runtime dependencies.
LET YOUR CONTENT GO PLACES

Ready to get moving?

One small library. A whole new way to bring your content to life.

Prefer the full guide? Find setup instructions, API contracts and lifecycle examples in the documentation.

Read the documentation