Urgent.News

What's breaking now, across thousands of outlets.

Tech

Your Timer Doesn't Know You Tabbed Away

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…

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.

The 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.

The 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.

The 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.

Implementing 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.

It'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.

Understanding 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.

Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.

Read the original at dev.to →

More in Tech

React Compiler 1.0: What useMemo You Can Delete

Open any React codebase built before late 2025 and you'll find the same defensive scaffolding in nearly every component: a memo() wrapper here, a useCallback there, a useMemo around a sort you were…

More from Saturday 5 September →