Counting down to a date, correctly
A countdown to a specific moment has to answer a question a simple duration does not: whose moment? An event at "midnight on 31 December" happens at 26 different instants around the world. Counting down correctly means fixing the target as an absolute instant — a UTC timestamp — and rendering the remaining time from each viewer's clock.
The alternative, comparing local wall-clock times, breaks for everyone outside the author's time zone and breaks again across daylight saving transitions, where a day may have 23 or 25 hours. Computing a day difference by dividing elapsed milliseconds by 86,400,000 produces off-by-one errors twice a year for exactly this reason.
It is also worth deciding what happens at zero. A countdown that continues into negative numbers is rarely what anyone wants; switching to a completed state, or counting up since the event, are both more useful.
Accuracy and the viewer's clock
A countdown computed in the browser depends on the device's clock, which can be wrong. Most devices synchronise over the network and are accurate within a second, but a device with an incorrect time will show an incorrect countdown, and there is no way for a page to know.
For anything where precision matters — a sale opening, a ticket release, a submission deadline — the authoritative time must be the server's, and the client should be reconciled against it rather than trusted. Fetching the server time once and computing an offset is the usual approach, and it removes the class of complaint where a user insists the countdown lied to them.
As with any browser timer, compute the remaining time from the target rather than by decrementing a counter, so background-tab throttling does not cause drift. A countdown that resumes accurately after a tab has been hidden for an hour is a direct consequence of this.
Using countdowns without irritating people
Countdowns work because deadlines genuinely affect behaviour, and they are correspondingly easy to abuse. A countdown that resets when the page is reloaded, or that restarts for each new visitor, is a fabricated deadline — and in several jurisdictions, including under the UK's consumer protection regulations and the EU's unfair commercial practices directive, presenting a false time limit is a prohibited practice rather than merely a dark pattern.
A genuine deadline is fine to display, and a countdown to a real event is useful information. The distinction is whether the deadline exists independently of the countdown.
Accessibility matters here too: a rapidly updating region should not be announced continuously by a screen reader, so either mark it aria-live="off" and provide the deadline as static text, or update the announcement at a coarse interval. Anyone relying on a countdown to complete a task also needs the ability to extend or turn it off — WCAG 2.2 requires a mechanism for adjusting time limits, and this is one of the more commonly missed criteria.