JavaScript Page Visibility API: Detect Background Tabs

The Page Visibility API is a native browser interface that allows web applications to detect when a user minimizes a window, switches tabs, or moves a webpage into the background. This article explains how the API works, outlines its core properties and events, and demonstrates how to use JavaScript to detect tab visibility changes to optimize application performance, manage media playback, and reduce server load.

What is the Page Visibility API?

Historically, developers relied on window focus and blur events (window.onfocus and window.onblur) to infer whether a user was interacting with a webpage. However, blur events trigger even when a user clicks outside the viewport (such as inside the developer tools or address bar), even if the page remains fully visible.

The Page Visibility API solves this by providing a reliable way to determine if a document is actually visible to the user on the screen. It helps web applications conserve CPU, network bandwidth, and battery life by pausing resource-intensive tasks when the page is hidden.

Core Properties and Events

The API provides two primary document properties and one event listener to track page visibility.

1. document.hidden

A read-only boolean value: * true: The page is not visible to the user (e.g., background tab, minimized window, or screen locked). * false: The page is at least partially visible on screen.

2. document.visibilityState

A read-only string representing the current visibility status of the page. It can return one of the following values: * "visible": The page is visible to the user and is the active tab in at least one window. * "hidden": The page is completely hidden from view.

(Note: Older implementations included "prerender" and "unloaded", but these are deprecated in modern specifications.)

3. The visibilitychange Event

This event fires on the document object whenever the value of document.visibilityState changes.

How to Detect Background Tabs in JavaScript

To track whether a user switches away from or returns to your tab, attach an event listener for the visibilitychange event.

document.addEventListener('visibilitychange', () => {
  if (document.hidden) {
    // Tab is in the background
    console.log('Tab is hidden');
    pauseHeavyTasks();
  } else {
    // Tab is in the foreground
    console.log('Tab is visible');
    resumeHeavyTasks();
  }
});

Using document.visibilityState directly:

document.addEventListener('visibilitychange', () => {
  if (document.visibilityState === 'hidden') {
    // Pause video playback, stop animations, or stop polling
    stopRealtimeUpdates();
  } else if (document.visibilityState === 'visible') {
    // Resume video playback or restart polling
    startRealtimeUpdates();
  }
});

Practical Use Cases