This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015.
The Page Visibility API provides events you can watch for to know when a document becomes visible or hidden, as well as features to look at the current visibility state of the page.
This is especially useful for saving resources and improving performance by letting a page avoid performing unnecessary tasks when the document isn't visible.
When the user minimizes the window, switches to another tab, or the document is entirely obscured by another window, the API sends a visibilitychange event to let listeners know the state of the page has changed. You can detect the event and perform some actions or behave differently. For example, if your web app is playing a video, it can pause the video when the user puts the tab into the background, and resume playback when the user returns to the tab. The user doesn't lose their place in the video, the video's soundtrack doesn't interfere with audio in the new foreground tab, and the user doesn't miss any of the video in the meantime.
Visibility states of an <iframe> are the same as the parent document. Hiding an <iframe> using CSS properties (such as display: none;) doesn't trigger visibility events or change the state of the document contained within the frame.
Let's consider a few use cases for the Page Visibility API.
Developers have historically used imperfect proxies to detect this. For example, watching for blur and focus events on the window helps you know when your page is not the active page, but it does not tell you that your page is actually hidden to the user. The Page Visibility API addresses this.
Note: While onblur and onfocus will tell you if the user switches windows, it doesn't necessarily mean it's hidden. Pages only become hidden when the user switches tabs or minimizes the browser window containing the tab.
Separately from the Page Visibility API, user agents typically have a number of policies in place to mitigate the performance impact of background or hidden tabs. These may include:
requestAnimationFrame() callbacks to background tabs or hidden <iframe>s in order to improve performance and battery life.setTimeout() are throttled in background/inactive tabs to help improve performance. See Reasons for delays longer than specified for more details.Some processes are exempt from this throttling behavior. In these cases, you can use the Page Visibility API to reduce the tabs' performance impact while they're hidden.
The Page Visibility API adds the following properties to the Document interface:
Returns true if the page is in a state considered to be hidden to the user, and false otherwise.
Document.visibilityState Read only
A string indicating the document's current visibility state. Possible values are:
visibleThe page content may be at least partially visible. In practice this means that the page is the foreground tab of a non-minimized window.
The page's content is not visible to the user, either due to the document's tab being in the background or part of a window that is minimized, or because the device's screen is off.
The Page Visibility API adds the following events to the Document interface:
visibilitychangeFired when the content of a tab has become visible or has been hidden.
This example pauses playing audio when the page is hidden and resumes playing when the page becomes visible again. The <audio> element controls allow the user to toggle between playing and paused audio. The boolean playingOnHide is used to prevent audio from playing if the page changes to a visible state, but the media wasn't playing on page hide.
<audio controls src="https://mdn.github.io/webaudio-examples/audio-basics/outfoxing.mp3"></audio>
const audio = document.querySelector("audio");
let playingOnHide = false;
document.addEventListener("visibilitychange", () => {
if (document.hidden) {
playingOnHide = !audio.paused;
audio.pause();
} else if (playingOnHide) {
// Page became visible! Resume playing if audio was "playing on hide"
audio.play();
}
});
| Specification |
|---|
| HTML> # dom-document-visibilitystate> |
| Desktop | Mobile | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android | WebView on iOS | |
Page_Visibility_API |
3313 | 12 | 1810–52 | 201512.1–15 | 7 | 3318 | 1810–52 | 201412.1–14 | 7 | 2.01.0 | 4.4.34.4 | 7 |
Document.visibilityStateDocument.hidden
© 2005–2025 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API