webdevpuneet.com

Delivery ETA Card — Free Countdown & Progress Courier Card

Delivery ETA Card · Cards · Plain HTML, CSS & JS · Live preview

CategoryCards

Copy & paste

Source Code

<div class="de-card">
  <div class="de-top">
    <span class="de-eyebrow">Arriving in</span>
    <div class="de-countdown" id="deCountdown">2h 15m</div>
  </div>

  <div class="de-progress">
    <div class="de-progress-track">
      <div class="de-progress-fill" id="deFill"></div>
    </div>
    <div class="de-progress-labels">
      <span>Warehouse</span>
      <span id="deDistance">4.2 mi left</span>
      <span>Your door</span>
    </div>
  </div>

  <div class="de-courier">
    <span class="de-avatar">MK</span>
    <div class="de-courier-info">
      <strong>Maria K.</strong>
      <span>Your courier</span>
    </div>
    <button class="de-contact" id="deContact" type="button">Contact courier</button>
  </div>
  <div class="de-toast" id="deToast">Calling Maria K. …</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 countdown
Large tabular-numeral time-remaining display.
Synced progress bar
Fill and distance derive from one ratio.
Avatar-initial identity
No photo dependency, always renders.
Contact button with toast
In-card feedback with no page navigation.
Compact card layout
Fits a sidebar, modal, or app widget.
Smooth fill transition
CSS transition animates progress changes.
Formatted time helper
Switches between "Nh Nm" and "Nm" cleanly.
No dependencies
Pure HTML, CSS, and JavaScript.

About this UI Snippet

Delivery ETA Card — A Compact Countdown Card for the Last Mile

Screenshot of the Delivery ETA Card snippet rendered live

The delivery ETA card is the small, glanceable card food-delivery and courier apps show once an order is out for delivery — a countdown, a progress bar, and a way to reach the driver, all in one compact block. This snippet builds it in plain HTML, CSS, and JavaScript.

Countdown as the headline

The top of the card is a large, tabular-numeral countdown ("2h 15m") formatted by a small format() helper that switches between "Nh Nm" and "Nm" once the hour count hits zero. font-variant-numeric: tabular-nums keeps the digits from jittering in width as they change.

Progress tied to the same countdown

The progress bar's fill width and the "X mi left" label are both derived from the same remainingSeconds / totalSeconds ratio the countdown uses — so the bar, the distance label, and the time all stay mathematically consistent instead of being three separately animated pieces that can drift apart.

Avatar-initial courier identity

Rather than loading a photo, the courier is represented by a colored circle with their initials ("MK") — a lightweight, always-available identity pattern that avoids broken image states and loads instantly.

A contact action with feedback

The "Contact courier" button doesn't navigate away; it shows a small toast ("Calling Maria K. …") that fades in and back out, giving the user confirmation the tap registered — the same micro-interaction pattern used across delivery apps for in-card actions.

A self-contained demo timer

The JavaScript uses setInterval to advance the countdown for demonstration purposes (each tick represents a simulated minute). In production you'd replace this with a value computed from your delivery-tracking backend or recalculated from a real ETA timestamp on each poll.

Customizing it

Swap the countdown source for a real ETA timestamp, replace the avatar initials with a photo with a graceful fallback, or add a small map thumbnail. Pair it with a package tracking route or order tracking timeline.

Step by step

How to Use

  1. 1
    Paste HTML, CSS, and JSThe card renders with a starting countdown.
  2. 2
    Watch it count downThe demo timer advances every few seconds.
  3. 3
    Watch the progress barFill and distance stay in sync with the timer.
  4. 4
    Click "Contact courier"A toast confirms the action.
  5. 5
    Wire to real dataReplace remainingSeconds with a live ETA.

Real-world uses

Common Use Cases

Food delivery tracking
Show a live courier countdown after an order is out for delivery, with tabular numerals so the time never jitters as digits change.
Package tracking pairings
Place beside a package tracking map so the route and the arrival time are visible together.
Driver arrival cards
Reuse the pattern for ride-style apps, where a progress bar and distance remaining derive from one ratio.
Order confirmation pages
Sit beside an order summary, with an avatar initial for the courier so it renders without any photo.
Operations and support views
Give agents a quick contact-courier shortcut, or combine with a status dashboard for operations teams watching many deliveries.
Related: Motion One Spring Card Expand
See the Motion One Spring Card Expand for a related cards pattern worth pairing with this one.

Got questions?

Frequently Asked Questions

No — the demo advances remainingSeconds locally via setInterval to show the pattern. In production, recompute remainingSeconds from a real ETA timestamp each time you poll or receive a push update, rather than trusting client-side elapsed time alone.

Both are derived from the same elapsedRatio value (1 - remainingSeconds / totalSeconds) inside a single tick() function, so there's one source of truth instead of three independently updated elements that could drift apart.

Initials in a colored circle render instantly with no network request and never show a broken-image icon. It's a common fallback pattern — you can layer a real <img> on top with an onerror handler that falls back to the initials if you want photos when available.

In this snippet it shows a toast as a placeholder for the real action. In production, wire the click handler to open a masked-number call, an in-app chat thread, or a deep link, and keep the toast (or a similar confirmation) as feedback that the tap registered.

Move remainingSeconds into component state, replace the setInterval-based tick with your framework's timer/effect pattern (recomputing from a real ETA when available), and bind the fill width, countdown text, and distance label to that state. The CSS ports unchanged.