Tiny countdown Web Component. Registers <countdown-timer> that renders a configurable DD:HH:MM:SS countdown to a target date/time (optional UTC offset) and fires a done event at zero.
npm install zero-hourzero-hour
ZeroHour is a tiny countdown Web Component. It registers <countdown-timer> that renders a DD:HH:MM:SS countdown (with configurable visible units), counts down to a target date/time with an optional UTC offset, ticks on exact second boundaries, and fires a done event when it reaches zero.



➠ Install
``console`
yarn add zero-hour
➠ Import
`javascript
// Registers
import 'zero-hour';
// Optional helper: subscribe to done and apply stylesheets`
import { initCountdownTimers } from 'zero-hour';
➠ Usage
`javascript`
// After importing 'zero-hour', the element is registered.
// Then just place
HTML: default start (autostart=true)
`html`
separator-url="/sprites/sep.webp"
date="2025-12-31"
time="23:59:59"
utc="+03:00"
>
JS: subscribe to completion + optional styles
`javascript
import { initCountdownTimers } from 'zero-hour';
initCountdownTimers({
selector: 'countdown-timer',
onDone: (el) => {
// The component dispatches: el.dispatchEvent(new CustomEvent('done'))
// Note: if the timer is already complete (e.g. user opened the page after the target time),
// initCountdownTimers will call onDone immediately (catch-up).`
el.classList.add('is-done');
},
// Optional styles:
// - CSSStyleSheet (constructable stylesheet)
// - string (e.g. imported via ?raw from your CSS/SCSS pipeline)
// stylesheet: myCssStyleSheet,
});
JS: custom styles from ?raw (CSS/SCSS)
`javascript
import { initCountdownTimers } from 'zero-hour';
import ZeroHourCss from './assets/scss/components/zero-hour.scss?raw';
initCountdownTimers({
stylesheet: ZeroHourCss,
});
`
JS: default styles shipped with the package
`javascript
import { initCountdownTimers, zeroHourCssText } from 'zero-hour';
// Option A: use the built-in CSS text export
initCountdownTimers({
stylesheet: zeroHourCssText,
});
// Option B: import the package CSS file as raw text (your bundler must support ?raw)
// import ZeroHourCss from 'zero-hour/zero-hour.css?raw';
// initCountdownTimers({ stylesheet: ZeroHourCss });
`
JS: manual control (start/stop/reset)
`javascript`
const el = document.querySelector('countdown-timer');
// @ts-expect-error: methods exist on the custom element instance after import
el?.stop();
// @ts-expect-error
el?.reset();
// @ts-expect-error
el?.start();
Units (units)
`html`
separator-url="/sprites/sep.webp"
date="2025-12-31"
time="23:59:59"
utc="+03:00"
units="h:m:s"
>
➠ Options
| Option (attribute) | Type | Default | Description |
|:--------------------:|:-----------------------:|:------------:|:---------------------------------------------------------------------------------------------------------------------------------------------------------|
| digits-url | string | — | URL to the digits sprite sheet. Required for the graphical display (otherwise only a text fallback is updated in the a11y layer). |separator-url
| | string | null | URL to the separator sprite (e.g. a colon). If omitted, separators are hidden. |autostart
| | boolean | true | Auto-start on connect. Can be a boolean attribute (autostart) or a string (autostart="false"). |date
| | YYYY-MM-DD | — | Target date. Without date the timer resolves to zero. |time
| | HH:MM[:SS] | 00:00:00 | Target time. |utc
| | UTC±H[:MM] or ±H[:MM] | UTC+0 | UTC offset used to compute the target moment. Examples: utc="UTC+03:00", utc="UTC-5". |units
| | string | "d:h:m:s" | Visible groups pattern using d, h, m, s separated by : (e.g. "h:m:s"). Empty/invalid value falls back to showing all. |mode
| | "static" \| "scroll" | "static" | Digit transition mode. scroll animates digits (rolling effect), static swaps without scroll. |
➠ API Methods
| Method | Description |
|-------------------|--------------------------------------------------------------------------------------------------|
| initCountdownTimers({ selector?, onDone?, stylesheet? }): HTMLElement[] | Finds elements by selector (default: countdown-timer), subscribes to the done event (when onDone is provided), and calls onDone immediately if a timer is already complete at init time (catch-up). Also optionally applies styles to each element (stylesheet?: CSSStyleSheet \| string \| null). When a string is provided, it is applied via adoptedStyleSheets when supported, otherwise via a