StockTicker Marquee Widgets: 7 Customization Tips for Accurate Quotes

How to Build a StockTicker Marquee with HTML, CSS & JavaScript

Overview

Create a lightweight, accessible, and responsive scrolling stock ticker that fetches real-time or simulated prices and displays symbol, price, change, and change color. This guide assumes you’ll fetch data via an API or WebSocket; if not available, it uses simulated updates.

Files

  • index.html
  • styles.css
  • app.js

HTML (structure)

html

<!doctype html> <html lang=en> <head> <meta charset=utf-8 /> <meta name=viewport content=width=device-width,initial-scale=1 /> <title>StockTicker Marquee</title> <link rel=stylesheet href=styles.css /> </head> <body> <div class=ticker role=region aria-label=Stock ticker> <div class=tickertrack id=tickerTrack aria-live=polite></div> </div> <script src=app.js></script> </body> </html>

CSS (styles.css)

css

:root{ –bg:#0b1220; –text:#e6eef8; –up:#28a745; –down:#d93636; –muted:#95a3b8; –height:48px; –gap:32px; } *{box-sizing:border-box} body{margin:0;font-family:Inter,system-ui,-apple-system,Segoe UI,Roboto,“Helvetica Neue”,Arial;background:var(–bg);color:var(–text);display:flex;align-items:center;justify-content:center;height:100vh} .ticker{ width:100%; max-width:1100px; background:linear-gradient(90deg, rgba(255,255,255,0.02), rgba(255,255,255,0.01)); border-radius:8px; padding:6px 12px; overflow:hidden; height:var(–height); display:flex; align-items:center; } .tickertrack{ display:flex; gap:var(–gap); align-items:center; will-change:transform; white-space:nowrap; animation:scroll 25s linear infinite; } .tickeritem{ display:inline-flex; align-items:center; gap:8px; padding:6px 10px; border-radius:6px; background:transparent; color:var(–text); font-size:14px; } .tickersymbol{font-weight:700} .tickerprice{min-width:70px;text-align:right;font-variant-numeric:tabular-nums} .tickerchange{padding-left:8px;font-variant-numeric:tabular-nums} .tickerup{color:var(–up)} .tickerdown{color:var(–down)} .tickermuted{color:var(–muted);font-weight:600} @keyframes scroll{ 0%{transform:translateX(0)} 100%{transform:translateX(-50%)} } /* Pause on hover for accessibility */ .ticker:hover .tickertrack, .ticker:focus-within .tickertrack{ animation-play-state:paused; }

JavaScript (app.js)

js

// Config const symbols = [‘AAPL’,‘MSFT’,‘GOOGL’,‘AMZN’,‘TSLA’,‘NVDA’,‘META’,‘BABA’]; const track = document.getElementById(‘tickerTrack’); const updateInterval = 3000; // ms for simulated updates // Utility: format price & change const fmt = num => Number(num).toLocaleString(undefined, {minimumFractionDigits:2, maximumFractionDigits:2}); const sign = n => (n>0?’+’:(n<0?’-’:)); // Create item element function createItem(sym, price, change){ const item = document.createElement(‘div’); item.className = ‘tickeritem’; item.innerHTML = </span><span class="token template-string" style="color: rgb(163, 21, 21);"> </span><span class="token template-string" style="color: rgb(163, 21, 21);"> <span class="ticker__symbol"></span><span class="token template-string interpolation interpolation-punctuation" style="color: rgb(57, 58, 52);">${</span><span class="token template-string interpolation">sym</span><span class="token template-string interpolation interpolation-punctuation" style="color: rgb(57, 58, 52);">}</span><span class="token template-string" style="color: rgb(163, 21, 21);"></span> </span><span class="token template-string" style="color: rgb(163, 21, 21);"> <span class="ticker__price">$</span><span class="token template-string interpolation interpolation-punctuation" style="color: rgb(57, 58, 52);">${</span><span class="token template-string interpolation" style="color: rgb(57, 58, 52);">fmt</span><span class="token template-string interpolation" style="color: rgb(57, 58, 52);">(</span><span class="token template-string interpolation">price</span><span class="token template-string interpolation" style="color: rgb(57, 58, 52);">)</span><span class="token template-string interpolation interpolation-punctuation" style="color: rgb(57, 58, 52);">}</span><span class="token template-string" style="color: rgb(163, 21, 21);"></span> </span><span class="token template-string" style="color: rgb(163, 21, 21);"> <span class="ticker__change </span><span class="token template-string interpolation interpolation-punctuation" style="color: rgb(57, 58, 52);">${</span><span class="token template-string interpolation">change</span><span class="token template-string interpolation" style="color: rgb(57, 58, 52);">></span><span class="token template-string interpolation" style="color: rgb(54, 172, 170);">0</span><span class="token template-string interpolation" style="color: rgb(57, 58, 52);">?</span><span class="token template-string interpolation" style="color: rgb(163, 21, 21);">'ticker__up'</span><span class="token template-string interpolation" style="color: rgb(57, 58, 52);">:</span><span class="token template-string interpolation" style="color: rgb(57, 58, 52);">(</span><span class="token template-string interpolation">change</span><span class="token template-string interpolation" style="color: rgb(57, 58, 52);"><</span><span class="token template-string interpolation" style="color: rgb(54, 172, 170);">0</span><span class="token template-string interpolation" style="color: rgb(57, 58, 52);">?</span><span class="token template-string interpolation" style="color: rgb(163, 21, 21);">'ticker__down'</span><span class="token template-string interpolation" style="color: rgb(57, 58, 52);">:</span><span class="token template-string interpolation" style="color: rgb(163, 21, 21);">'ticker__muted'</span><span class="token template-string interpolation" style="color: rgb(57, 58, 52);">)</span><span class="token template-string interpolation interpolation-punctuation" style="color: rgb(57, 58, 52);">}</span><span class="token template-string" style="color: rgb(163, 21, 21);">"> </span><span class="token template-string" style="color: rgb(163, 21, 21);"> </span><span class="token template-string interpolation interpolation-punctuation" style="color: rgb(57, 58, 52);">${</span><span class="token template-string interpolation" style="color: rgb(57, 58, 52);">sign</span><span class="token template-string interpolation" style="color: rgb(57, 58, 52);">(</span><span class="token template-string interpolation">change</span><span class="token template-string interpolation" style="color: rgb(57, 58, 52);">)</span><span class="token template-string interpolation interpolation-punctuation" style="color: rgb(57, 58, 52);">}</span><span class="token template-string interpolation interpolation-punctuation" style="color: rgb(57, 58, 52);">${</span><span class="token template-string interpolation">Math</span><span class="token template-string interpolation" style="color: rgb(57, 58, 52);">.</span><span class="token template-string interpolation" style="color: rgb(57, 58, 52);">abs</span><span class="token template-string interpolation" style="color: rgb(57, 58, 52);">(</span><span class="token template-string interpolation">change</span><span class="token template-string interpolation" style="color: rgb(57, 58, 52);">)</span><span class="token template-string interpolation" style="color: rgb(57, 58, 52);">.</span><span class="token template-string interpolation" style="color: rgb(57, 58, 52);">toFixed</span><span class="token template-string interpolation" style="color: rgb(57, 58, 52);">(</span><span class="token template-string interpolation" style="color: rgb(54, 172, 170);">2</span><span class="token template-string interpolation" style="color: rgb(57, 58, 52);">)</span><span class="token template-string interpolation interpolation-punctuation" style="color: rgb(57, 58, 52);">}</span><span class="token template-string" style="color: rgb(163, 21, 21);"> </span><span class="token template-string" style="color: rgb(163, 21, 21);"> </span></span><span class="token template-string template-punctuation" style="color: rgb(163, 21, 21);">; return item; } // Simulate initial prices const state = {}; symbols.forEach(s=>{ state[s] = {price: Math.random()150+50}; }); // Render items twice for seamless loop function render(){ track.innerHTML = ; const fragment = document.createDocumentFragment(); symbols.forEach(s=>{ fragment.appendChild(createItem(s, state[s].price, state[s].change || 0)); }); // duplicate const frag2 = fragment.cloneNode(true); track.appendChild(fragment); track.appendChild(frag2); } render(); // Simulate updates (replace with real API/WebSocket) function randomWalk(){ symbols.forEach(s=>{ const p = state[s].price; const delta = (Math.random()-0.48) (p 0.01); // ~1% moves const newP = Math.max(0.01, p + delta); state[s].change = newP - p; state[s].price = newP; }); render(); } // Example of integrating a real API (pseudo): // fetch(‘/api/prices’).then(r=>r.json()).then(data => { / update state and render */ }); // Start updates setInterval(randomWalk, updateInterval);

Accessibility & Performance Notes

  • Use aria-live or role=region to announce updates; pause animation on hover/focus.
  • For real-time data, prefer WebSocket for low-latency updates; fall back to polling.
  • Duplicate the track contents for smooth infinite scrolling, or use CSS scroll snapping for different effects.
  • Keep DOM updates minimal: update text nodes rather than reconstructing whole DOM for high-frequency updates.

Deployment tips

  • Host only necessary assets; minify CSS/JS.
  • Cache static assets and use rate limits for API calls.
  • If using third-party market data, check usage limits and display disclaimers if required.

If you want, I can convert this into a single-file example or show a WebSocket integration example.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *