webdevpuneet.com

Live Market Watchlist Table — Free HTML CSS JS Snippet

Live Market Watchlist Table · Tables · Plain HTML, CSS & JS · Live preview

CategoryTables

Copy & paste

Source Code

<div class="wrap">
  <div class="table-head">
    <h2 class="table-title">Watchlist</h2>
    <span class="live-dot"><i></i>Live</span>
  </div>
  <div class="table-scroll">
    <table class="tbl">
      <thead>
        <tr>
          <th>Symbol</th>
          <th class="num">Price</th>
          <th class="num">24h change</th>
          <th class="spark-col">Trend</th>
        </tr>
      </thead>
      <tbody id="tbody"></tbody>
    </table>
  </div>
</div>

Extend with AI

Take This Snippet Further With AI

The AI prompt for this one is for Patreon supporters ($3 a month), along with a site with no ads. Supporters enter the passcode once and it is remembered in this browser.

· Become a supporter

What's included

Features

Live simulated price stream updates every 1.6 seconds via a repeating interval
Row briefly flashes green or red matching the direction of that specific price change
Forced reflow (offsetWidth read) restarts the flash CSS transition even on consecutive same-direction moves
Per-asset sparkline normalizes to its own rolling price history, not a shared fixed scale
Percentage change always measured against a fixed session-start baseline, not the previous tick
Only the changed price, badge, and sparkline DOM nodes update per tick — the table body is never fully re-rendered after initial load
Rolling 12-point history window keeps each sparkline focused on recent movement
Up/down direction reinforced with both color and an arrow glyph for redundant signaling

About this UI Snippet

Live Market Watchlist Table — Flash-on-Change Rows, Live Sparklines & Surgical DOM Updates

Screenshot of the Live Market Watchlist Table snippet rendered live

A price table that silently updates numbers in place is easy to miss changes in — a trader or investor glancing away for a few seconds has no way to tell whether a price just moved or has been sitting still the whole time. This watchlist solves that with a brief background-color flash on any row whose price just changed, colored green or red by direction, alongside a live sparkline trend line per asset that updates every tick.

Surgical per-cell updates, not a full re-render

render() builds the entire table once on load, but the repeating updatePrices() function never calls it again. Instead, it looks up each row by data-symbol, then updates exactly three things inside it directly: the price text node, the change badge's class and innerHTML, and the sparkline polyline's points and stroke attributes. This distinction is what makes the flash animation possible at all — if the whole table re-rendered from scratch every tick, any CSS transition or flash class added a moment earlier would be wiped out along with the stale DOM node it was attached to.

Restarting a CSS transition with a forced reflow

When a row's price moves in the *same* direction two ticks in a row, simply re-adding the same .flash-up class would have no visible effect — the class is already present, so no transition triggers. updatePrices() handles this by removing both flash classes, reading row.offsetWidth (a layout property read that forces the browser to flush pending style changes before continuing — a well-known technique for restarting CSS animations), and only then re-adding the appropriate flash class. Without that forced reflow, a stock moving up for three consecutive ticks would only flash on the first one.

Self-normalizing sparklines from a rolling history window

Each asset carries its own history array, capped at 12 points via .shift() once new prices push it over that length. sparkPoints() normalizes each point between that array's own current min and max, so the sparkline always uses its full available height regardless of whether the asset has been range-bound or has just had a sharp move — a fixed y-axis scale shared across all assets would flatten a low-volatility asset's line to a nearly straight one.

Percent change measured against a fixed baseline, not the previous tick

pctChange() always compares the current price to basePrices, a value captured once when the page loaded (the first entry in each asset's initial history) — not to the price one tick earlier. This mirrors how a real "24h change" figure works: it should represent total movement since a fixed reference point, not reset itself relative to whatever the price happened to be a moment ago.

Step by step

How to Use

  1. 1
    Watch it update liveEvery 1.6 seconds, prices nudge randomly — the changed price, percentage badge, and sparkline update in place, with the row briefly flashing green or red.
  2. 2
    Replace ASSETS with real symbolsSet each asset's symbol, name, starting price, and initial history array to real data from your market data provider.
  3. 3
    Connect a real price feedReplace the setInterval(updatePrices, 1600) simulation with a WebSocket or polling callback from your market data API that sets a.price directly before running the same DOM-update logic.
  4. 4
    Adjust the flash durationChange the 550 in the setTimeout call and the 0.5s in the CSS transition to make the flash linger longer or shorter.
  5. 5
    Change the sparkline history windowEdit the "if (a.history.length > 12)" check to show a longer or shorter recent trend per asset.
  6. 6
    Export in your formatClick "HTML" for a standalone file, "JSX" for a React component, or "Tailwind" for a Tailwind CSS version.

Real-world uses

Common Use Cases

Crypto and stock trading dashboards
The core use case — a personal or platform watchlist showing live price movement across multiple assets at a glance.
Portfolio tracking apps
Adapt the same flash-and-sparkline pattern to show live gain/loss per holding in a personal investment tracker.
Trading terminal and market data widgets
Embed as one panel inside a larger trading terminal alongside order books and charts.
Learn surgical live-update DOM patterns
A clean example of updating only the DOM nodes that actually changed on each tick, instead of re-rendering an entire list — directly transferable to any live-data table.
Sports odds and live-score tables
Repurpose the same flash-on-change and per-row trend pattern for live betting odds or sports score tickers instead of asset prices.

Got questions?

Frequently Asked Questions

If a row's price moves in the same direction on two consecutive ticks, simply re-adding the already-present .flash-up class triggers no CSS transition, since the class never actually left. Reading row.offsetWidth forces the browser to apply the class-removal style change immediately (a technique called a forced reflow) before the class is re-added, guaranteeing the transition restarts every time.

Rebuilding the entire tbody from scratch every 1.6 seconds would destroy and recreate every row, which would immediately erase any in-progress flash CSS transition and cause needless layout work. updatePrices() instead finds each row by its data-symbol attribute and updates only the price text, change badge, and sparkline polyline points directly.

pctChange() always compares the current price to basePrices, a value captured once from each asset's initial history when the page first loaded — not the price one tick earlier. This matches how a real "24h change" figure behaves: a running total change since a fixed reference point, not something that resets relative to the last tick.

sparkPoints() normalizes each asset's own history array between that array's current minimum and maximum, so every sparkline always uses its full available height — a shared fixed scale across assets would flatten a low-volatility asset's line to nearly a straight one.

Replace the setInterval(updatePrices, 1600) simulation with a WebSocket message handler (or polling call) from your market data provider that sets each asset's price property to the real incoming value, then reuses the same DOM-update block that already exists inside updatePrices() for the flash, badge, and sparkline logic.

Each asset's history array is capped at 12 entries via a .shift() call once a new price push exceeds that length, keeping the sparkline focused on roughly the most recent 12 ticks rather than growing unbounded.