Back to Widget Patterns
v2.1Urgency

Countdown Timer

Real-time countdown to a deadline, updating every second. Includes an expired state with a custom message. Use only with genuine deadlines; the pattern documents fake-urgency anti-patterns.

Live preview

Rendered with real component code. Each example demonstrates a documented variant.

Default countdown

Ends in

6 days 23 hours 59 minutes 59 seconds

Compact format

Ends in

02d 23h 59m 59s

Custom label

Early bird ends in

13 days 23 hours 59 minutes 59 seconds

React props

Configure the component via props in React or via attributes in HTML.

PropTypeDefaultDescription
deadlineDate | stringrequiredThe target datetime. ISO 8601 strings are parsed automatically. Must be a fixed, real deadline.
labelstring"Ends in"Context copy shown above the countdown display
expiredLabelstring"Deal ended"Text shown in place of the timer once the deadline has passed
format"full" | "compact""full""full" renders "2 days 3 hours 45 minutes 12 seconds"; "compact" renders "02d 03h 45m 12s"
onExpire() => voidundefinedCallback fired once when the timer transitions to the expired state
classNamestringundefinedExtra class applied to the root .cdt element

HTML usage

The HTML variant uses the same shared styles and class names. Drop into any stack.

<link rel="stylesheet" href="path/to/countdown-timer/styles.css">

<section
  class="cdt"
  data-deadline="2026-09-01T00:00:00Z"
  data-expired-label="Deal ended"
>
  <p class="cdt__label">Sale ends in</p>
  <p class="cdt__display" aria-live="off"></p>
</section>

<script src="path/to/countdown-timer/html/countdown.js"></script>

Customization

Override these CSS custom properties to integrate the component into your brand.

.cdt {
  --cdt-display-font: ui-monospace, "Cascadia Code", "Source Code Pro",
    Menlo, Consolas, "DejaVu Sans Mono", monospace;
  --cdt-display-font-size: 1.75rem;
  --cdt-display-color: var(--brand-ink, #102542);
  --cdt-display-font-weight: 600;
  --cdt-label-color: var(--brand-muted, #5a6a7a);
  --cdt-label-font-size: 0.875rem;
  --cdt-label-font-weight: 400;
  --cdt-gap: 0.375rem;
}