iLoveTimersiLoveTimers.com
Home / Guides / How browser timers measure time
Written by Suhas Sunder · Published July 21, 2026 · Last reviewed July 21, 2026

How Browser Timers Measure Elapsed Time and Handle Delays

Learn why accurate browser timers measure elapsed or target time instead of assuming every callback arrives on schedule.

How can a browser timer stay accurate when animation frames and timer callbacks are delayed?

Short answer: a reliable browser timer treats callbacks as opportunities to update the screen, not as the source of truth for time. It records a monotonic start or target reading, then calculates the current elapsed or remaining duration from a fresh reading. If a callback is late, the next calculation absorbs the delay instead of adding drift.

This distinction explains why a display can skip from 00:08 to 00:05 after a busy or hidden period and still be more accurate than one that smoothly shows every number while running three seconds late.

Scheduling a callback is not measuring a duration

setTimeout(), setInterval(), andrequestAnimationFrame() tell the browser when page code would like another turn. That turn can be delayed by other JavaScript, rendering, throttling, a hidden page, a frozen page, or operating-system scheduling. The requested delay is not a promise that the callback begins at an exact millisecond.

Consider a naive stopwatch that adds 100 milliseconds on every nominal 100-millisecond interval. If one callback arrives 350 milliseconds late, adding only 100 milliseconds loses 250 milliseconds. Repeating this error produces interval drift. A reconciled stopwatch instead computes something equivalent to:

elapsed = savedElapsed + (performance.now() - startedAt)

The callback controls how often the user sees a new value. The clock difference controls what that value is.

Why performance.now is useful for elapsed time

The High Resolution Time specification requires performance readings from the same time origin to use a monotonic clock. The difference between two chronologically recorded readings cannot be negative. That makes performance.now() well suited to measuring a duration within the current page.

By contrast, Date.now() represents wall-clock time. The device clock can be corrected by synchronization, changed manually, or shifted in presentation because of timezone settings. Wall-clock time is appropriate when a tool must show the current date or clock time. A monotonic duration clock is appropriate when the question is “how much time passed in this page?”

Monotonic does not mean laboratory-grade. Browser privacy controls can reduce resolution, the display refresh rate limits visible updates, and input, rendering, and device latency remain. It means the clock is designed not to jump backward during the measurement.

Countdowns use a target; stopwatches use a start

The production countdown timer records an end reading equal to the current monotonic reading plus the remaining duration. On each animation frame it sets remaining time to the nonnegative difference between that end and a fresh reading. When the difference reaches zero, it finishes once.

The production stopwatch records a start reading. Each update subtracts that start from the current monotonic reading. The shared elapsed-stopwatch hook used by the combined timer and study stopwatch also keeps a saved base for paused time, and it immediately reconciles when the document becomes visible again.

Pausing requires capturing the current difference before clearing the active start. Resuming starts a new monotonic segment from that saved base. Reset clears both. These state transitions matter as much as the arithmetic because accidentally reseeding a target on every render can make a countdown move its own finish line.

Clocks and metronomes need different sources of truth

A clock page answers “what time is it now?” Its display therefore derives from a fresh Date or Date.now() reading on each tick. Adding exactly one second per callback would turn a late callback into a permanently slow clock. UTC and Unix displays still depend on the correctness of the device's system clock.

Audio rhythm has another requirement. The production metronome uses a short JavaScript look-ahead loop, but schedules individual sound nodes on AudioContext.currentTime. JavaScript wakes often enough to place upcoming ticks on the audio timeline. This separates the audio appointment from minor variation in the next interval callback. The visual pulse can still lag or skip under load, and the browser audio stack is not a certified musical timing source.

What still happens during a long delay

  • A reconciled display jumps to the current value rather than replaying every missed intermediate frame.
  • Completion code cannot run while the page is frozen or discarded, even if the mathematical target has passed.
  • A sound scheduled only when JavaScript notices completion can be late or absent after a lifecycle interruption.
  • A closed page loses in-memory monotonic state unless that particular tool deliberately saves enough information to restore it.
  • A page reload creates a new performance time origin, so old raw performance readings are not portable across reloads.

How to judge a browser timer claim

Ask which clock is used, what state is recorded, how late callbacks are reconciled, what happens after visibility changes, and whether the claim concerns mathematical duration, display refresh, audio delivery, or an external time authority. “Shows milliseconds” describes display formatting. It does not by itself establish millisecond measurement accuracy.

iLoveTimers uses browser timing for practical everyday tools. It does not claim official atomic synchronization, laboratory measurement, or guaranteed background execution. The implementation choices reduce ordinary callback drift while preserving those limits honestly.

Sources and further reading

These external references support the browser and standards behavior described above. iLoveTimers implementation details are identified separately in the guide.

  • W3C High Resolution Time: requires performance.now readings with the same time origin to use a monotonic clock and never move backward
  • HTML Standard: Timers: defines setTimeout and setInterval as mechanisms that schedule callbacks after a delay
  • MDN: setTimeout(): documents late callbacks, event-loop delay, and throttling in inactive tabs

Related iLoveTimers guides