webdevpuneet.com

Restaurant Order Status Tracker — Free Animated Step Tracker

Restaurant Order Status Tracker · Dashboards · Plain HTML, CSS & JS · Live preview

CategoryDashboards

Copy & paste

Source Code

<div class="ros-card">
  <div class="ros-head">
    <span class="ros-order-id">Order #4821</span>
    <span class="ros-eta" id="rosEta">Ready in ~12 min</span>
  </div>

  <ol class="ros-steps" id="rosSteps">
    <li class="ros-step" data-step="received">
      <span class="ros-dot"><span class="ros-pulse"></span></span>
      <span class="ros-label">Received</span>
    </li>
    <li class="ros-step" data-step="preparing">
      <span class="ros-dot"><span class="ros-pulse"></span></span>
      <span class="ros-label">Preparing</span>
    </li>
    <li class="ros-step" data-step="ready">
      <span class="ros-dot"><span class="ros-pulse"></span></span>
      <span class="ros-label">Ready</span>
    </li>
    <li class="ros-step" data-step="delivered">
      <span class="ros-dot"><span class="ros-pulse"></span></span>
      <span class="ros-label">Delivered</span>
    </li>
  </ol>

  <p class="ros-note" id="rosNote">Your order has been sent to the kitchen.</p>

  <div class="ros-controls">
    <button type="button" class="ros-btn" id="rosBack">Back</button>
    <button type="button" class="ros-btn ros-btn-primary" id="rosNext">Advance status</button>
  </div>
</div>

Extend with AI

Take This Snippet Further With AI

The AI prompt for this one is for Patreon supporters ($3 a month, 7 days free), 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

Index-driven state
One current index derives every step's class.
Layered pulse animation
Inner dot scale plus an outward sonar ring.
Auto-managed animation
Pulse starts/stops with the active class alone.
Progressive connecting line
Fills as each step completes.
Synced ETA and note copy
Parallel arrays keyed by the same index.
Self-disabling controls
Advance/back disable at each end of the flow.
Semantic ordered list
Built on ol/li for order and accessibility.
Zero dependencies
Plain HTML, CSS, and JS, no CDN.

About this UI Snippet

Restaurant Order Status Tracker — A Pulsing Horizontal Stepper

Screenshot of the Restaurant Order Status Tracker snippet rendered live

The restaurant order status tracker is the horizontal progress bar food delivery and pickup apps use to show where an order stands — Received, Preparing, Ready, Delivered — with the current step visibly pulsing and an estimated time note underneath. This snippet builds it in plain HTML, CSS, and JavaScript, no dependencies.

Three step states, one class each

Every step in the <ol> can be plain, .ros-done, or .ros-active. render() derives all three purely from a single current index — steps before it get .ros-done, the step at it gets .ros-active, everything else stays unstyled. Connecting lines between steps use a .ros-done check on each step's own ::before pseudo-element, so the line-fill and dot-fill both track the same index without extra bookkeeping.

A pulsing active step, built from two animations

The active dot layers two effects: an inner .ros-pulse dot that scales up and down on a 1.4s loop, and an outer ::after ring that expands and fades outward like a sonar ping. Both are pure CSS @keyframes running only while .ros-active is present, so the pulse starts and stops automatically as current changes — no setInterval needed to manage it.

An ETA that changes with status

The pill in the header and the note below the stepper both read from parallel arrays (etas, notes) indexed by current, so advancing the status updates the copy and the time estimate together — "Ready in ~18 min" while preparing, "Ready now" once ready, "Delivered" at the end.

Demo controls you'd replace with real events

The Back/Advance buttons exist so you can see every state in this demo; in production you'd call render() (after updating current) from your own order-status webhook or polling handler instead of a click. The Advance button disables and relabels itself "Completed" once the order reaches the final step.

Customizing it

Add a fifth step for multi-stage delivery (Preparing → Out for delivery → Delivered), swap the dot pulse for a different loading indicator, or connect the note text to real kitchen timing data. Pair it with an order tracking timeline, order summary, or a menu item customizer upstream in the ordering flow.

Step by step

How to Use

  1. 1
    Paste HTML, CSS, and JSA four-step order tracker renders at "Received".
  2. 2
    Click Advance statusThe active step pulses and the note/ETA update.
  3. 3
    Watch completed steps fillPast steps and their connecting lines turn green.
  4. 4
    Reach DeliveredThe advance button disables and reads "Completed".
  5. 5
    Wire real eventsCall render() after updating current from your own data.
  6. 6
    Add or rename stepsExtend the steps list, notes, and etas arrays together.

Real-world uses

Common Use Cases

Delivery app order screens
Follow an order summary with a live step tracker, where one current index derives every step's class.
Restaurant pickup screens
Show order status on an in-store display, with the active step pulsing through a layered inner dot and an outward ring.
Order tracking pages
Use it as a compact sibling of the order tracking timeline, with a connecting line that fills as each step completes.
Kitchen display systems
Reuse the pulse for an active ticket, which starts and stops automatically with the active class alone.
Coffee shops and catering
Track a drink from order to pickup, or show multi-step prep status to a catering customer, with an estimated-time note.

Got questions?

Frequently Asked Questions

render() reads a single current index and derives every step's visual state from a comparison against it — indexes below current get the ros-done class, the index equal to current gets ros-active, and everything else is untouched. The connecting lines and dot fills both read the same ros-done class, so nothing can fall out of sync.

The active dot layers two independent CSS keyframe animations: an inner .ros-pulse element that scales and fades on a loop, and an outer ::after ring pseudo-element that expands outward and fades like a sonar ping. Both only run while the parent carries the ros-active class, so they start and stop automatically as the class is toggled.

Two parallel arrays, notes and etas, are indexed by the same current variable that drives the step states, so advancing the status updates the header pill and the note paragraph in the same render() call that updates the stepper — there's only one source of truth for "what step are we on".

Replace the Back/Advance button handlers with your own event source — a webhook payload, a polling interval, or a websocket message — that sets current to the appropriate step index (0 for Received through 3 for Delivered) and calls render(). The demo buttons are only there so you can preview every state.

Yes — add a new li.ros-step with its own data-step value in the HTML, and add matching entries to the notes and etas arrays at the same index. render() and the CSS rules are generic over the number of steps, so no other logic changes are required.