{
  "id": 5763450,
  "title": "Your Timer Doesn't Know You Tabbed Away",
  "url": "https://urgent.news/2026/09/05/your-timer-doesnt-know-you-tabbed-away",
  "topic": "tech",
  "section": "Tech",
  "published": "2026-09-05T10:17:18.000Z",
  "source": {
    "name": "Dev.to",
    "slug": "dev-to",
    "url": "https://dev.to/parsajiravand/your-timer-doesnt-know-you-tabbed-away-3cjp"
  },
  "original_language": "en",
  "account": "A common issue arises when a timer running in a browser tab fails to account for when the tab is not actively visible to the user. Imagine a dashboard tile constantly polling an endpoint every two seconds, unaware that it's being ignored while the user switches to another application like Slack. This constant polling not only consumes server resources but also drains battery life unnecessarily.\n\nThe solution seems simple at first glance – pause the timer when the tab is blurred and resume it upon focusing again. However, this approach fails in many scenarios. For instance, when a video is supposed to play in the background, it may pause if the user clicks into DevTools or opens a browser extension's popup. Even worse, on multi-monitor setups, a dashboard might appear idle when it's fully visible on a second screen, simply because the user is typing in a different application on their primary monitor.\n\nThe problem stems from a misunderstanding of what the `blur` and `focus` events actually tell us. These events provide information about whether a window has keyboard focus, but they don't necessarily indicate whether a human is currently looking at the content. A window can lose focus while still being fully rendered and visible, as in the case of a second-monitor setup.\n\nThe real question we should be asking is whether the content is visible to a human. This is where the `document.visibilityState`, `document.hidden`, and the `visibilitychange` event come into play. These provide a more accurate measure of visibility, distinguishing between cases where the tab is switched away, minimized, or the screen is locked, and where the window is simply not visible to the user. Importantly, `document.hidden` is set to true when the tab is backgrounded or minimized, ensuring that our polling and other time-sensitive tasks are correctly paused or resumed.\n\nImplementing these changes involves swapping the blur/focus event listeners with the `visibilitychange` event listener. By checking `document.hidden`, we can accurately determine when our timer should be paused or resumed. However, we must also be careful not to rely solely on the timer's tick count, as browsers will throttle timers running in hidden tabs to save battery. Instead, we should track the actual elapsed time using `Date.now()` and reconcile this with our internal timer state.\n\nIt's crucial to distinguish between `focus`/`blur` events, which are relevant for keyboard interactions, and `visibilitychange` events, which are about whether the content is visible to a human. Using the appropriate event ensures that our application behaves correctly in all scenarios, whether the user is interacting with the content directly or if the content is running in the background.\n\nUnderstanding these distinctions and applying the correct event handling can prevent a host of issues, from videos stopping unexpectedly to polling intervals failing to update. By adopting these best practices, we can ensure that our applications respond correctly to user visibility, leading to a more efficient and reliable user experience.",
  "summary": "Picture a dashboard tile polling an endpoint every two seconds to keep a number fresh. You switch to Slack to answer a message. Four minutes later you're still there, and the tile is still polling — a request every two seconds, into a tab nobody has looked at since you left it. Multiply that by however many tabs your users leave open, and it's not a rounding error. It's server load and battery…",
  "key_points": [],
  "editors_take": null,
  "illustration": null,
  "coverage": {
    "outlets": 1,
    "also_reported_by": []
  },
  "ai_generated": true,
  "disclaimer": "Summaries, key points and the editor’s take are written by software from other outlets’ reporting and may contain errors — always check the linked original."
}