Explain Codes LogoExplain Codes Logo

Is there a way to detect if a browser window is not currently active?

javascript
cross-browser
page-visibility-api
event-handling
Anton ShumikhinbyAnton Shumikhin·Feb 25, 2025
TLDR

Promptly detect inactive browser tabs using the document.hidden attribute and the visibilitychange event listener. This event is triggered when a browser tab moves from active to inactive state, and vice versa.

document.addEventListener('visibilitychange', () => { console.log(`The browser tab is currently ${document.hidden ? 'taking a nap.' : 'awake and ready to party!'}`); });

The Page Visibility API, including document.hidden and the visibilitychange event, is well supported in modern browsers such as Chrome 13+, IE 10+, Firefox 10+ and Opera 12.10+. For older browsers that may lack support, window.onblur and window.onfocus events serve as decent fallback mechanisms.

Cross-browser support and fallbacks

With the varying support of visibility detection across browsers, implementing cross-browser compatible code is vital. Browsers may have specialized event names, so we tailor our code for different browser types.

let hidden, visibilityChange; if (typeof document.hidden !== "undefined") { // Opera 12.10 and above hidden = "hidden"; visibilityChange = "visibilitychange"; } else if (typeof document.msHidden !== "undefined") { // IE hidden = "msHidden"; visibilityChange = "msvisibilitychange"; } else if (typeof document.webkitHidden !== "undefined") { // Webkit browsers (Safari, Chrome) hidden = "webkitHidden"; visibilityChange = "webkitvisibilitychange"; } function handleVisibilityChange() { if (document[hidden]) { console.log("The tab's gone hibernating."); // Page is not visible } else { console.log("Tab's back with a bang!"); // Page is visible } } // If the browser doesn't support addEventListener or the Page Visibility API, raise an alert if (typeof document.addEventListener === "undefined" || typeof document[hidden] === "undefined") { alert("Switch to a browser that supports the Page Visibility API for this demo."); } else { // Handle the event when page visibility changes document.addEventListener(visibilityChange, handleVisibilityChange, false); }

This technique incorporates transparency layers for wider browser coverage despite the diversity in implementations.

Implementing smart detection

To improve the accuracy of detecting active engagement, we combine the Page Visibility API with user activity monitoring like scroll, mousemove and keypress events.

let timer, userIsActive = true; // Monitors prowling mice and eager fingers function activityMonitor() { clearTimeout(timer); userIsActive = true; timer = setTimeout(() => userIsActive = false, 5000); // If idle for 5 seconds, label as inactive } document.addEventListener('mousemove', activityMonitor); // Watch the mouse document.addEventListener('scroll', activityMonitor); // Catch those scrolls document.addEventListener('keypress', activityMonitor); // Monitor eager fingers document.addEventListener('visibilitychange', function() { if (document.hidden) { // Stop active tasks, alerting "Somebody stop me!" clearTimeout(timer); userIsActive = false; } else { // Resume tasks, triggering "Game on!" activityMonitor(); } });

This strategy brings to light unseen scenarios such as alt-tabbing in Chrome and minor traps in older browsers where visibilitychange could deceive us.

Periodic checks and further considerations

Implement periodic checks to ensure that non-active tabs cease running intensive tasks. Indeed, why tire out your CPU for an unaware audience, right?

setInterval(function() { if (!document.hidden && userIsActive) { // Perform tasks only if the tab is alive and kicking updateContent(); // "Tab refresh time! Stay hydrated, folks!" } }, 10000); // Checks every 10 seconds

Keep your developer tools close. Debugging with console.log ensures your event handlers aren't throwing secret parties.

Lastly, remember that detecting page visibility accurately every time is more challenging than finding a needle in a haystack. Adapt and test your code across different browsers and scenarios for the most accurate results.