The Page Visibility API lets you know when a webpage is visible or in focus. With tabbed browsing, there is a reasonable chance that any given webpage is in the background and thus not visible to the user. When the user minimizes the webpage or moves to another tab, the API sends a visibilitychange
event regarding the visibility of the page. You can detect the event and perform some actions or behave differently. For example, if your web app is playing a video, it would pause the moment the user looks at another browser, and plays again when the user returns to the tab. The user does not lose their place in the video and can continue watching.
Visibility states of an <iframe>
are the same as the parent document. Hiding the iframe with CSS properties does not trigger visibility events nor change the state of the content document.
Benefits
The API is particularly useful for saving resources by giving developers the opportunity to not perform unnecessary tasks when the webpage is not visible.
Use cases
A few examples:
- A site has an image carousel that shouldn't advance to the next slide unless the user is viewing the page.
- An application showing a dashboard of information doesn't want to poll the server for updates when the page isn't visible.
- A page wants to detect when it is being prerendered so it can keep accurate count of page views.
- A site wants to switch off sounds when a device is in standby mode (user pushes power button to turn screen off)
Developers have historically used imperfect proxies to detect this. For example, registering an onblur/onfocus handler on the window helps you know when your page is not the active page, but it does not tell you that your page is hidden to the user. The Page Visibility API addresses this. (When compared with registering onblur/onfocus handlers on the window, a key difference is that a page does not become hidden when another window is made active and the browser window loses focus. A page only becomes hidden when the user switches to a different tab or minimizes the browser window.)
Policies in place to aid background page performance
Along with the Page Visibility API, there are a number of policies in place to mitigate negative performance effects associated with background tabs:
Window.requestAnimationFrame()
calls are paused in most browsers when running in background tabs or hidden<iframe>
s in order to improve performance and battery life.- Timers such as
WindowOrWorkerGlobalScope.setTimeout
are throttled in background/inactive tabs to help improve performance. See Reasons for delays longer than specified for more details. - Budget-based background timeout throttling is now available in modern browsers (Firefox 58+, Chrome 57+), placing an additional limit on background timer CPU usage. This operates in a similar way across modern browsers, with the details being as follows:
- In Firefox, windows in background tabs each have their own time budget in milliseconds — a max and a min value of +50 ms and -150 ms, respectively. Chrome is very similar except that the budget is specified in seconds.
- Windows are subjected to throttling after 30 seconds, with the same throttling delay rules as specified for window timers (again, see Reasons for delays longer than specified.) In Chrome, this value is 10 seconds.
- Timer tasks are only permitted when the budget is non-negative.
- When a timer has executed, the execution time is deducted from the budget of the window where the timeout gets called from.
- The budget regenerates at a rate of 10 ms per second, in both Firefox and Chrome.
- Some processes are exempt from this throttling behaviour:
- Applications playing audio are considered foreground and aren’t throttled.
- Applications with real-time connections (WebSockets and WebRTC), to avoid closing these connections by timeout.
- IndexedDB processes.
Example
View live example (video with sound).
The example, which pauses the video when you switch to another tab and plays again when you return to its tab, was created with the following code:
// Set the name of the hidden property and the change event for visibility var hidden, visibilityChange; if (typeof document.hidden !== "undefined") { // Opera 12.10 and Firefox 18 and later support hidden = "hidden"; visibilityChange = "visibilitychange"; } else if (typeof document.msHidden !== "undefined") { hidden = "msHidden"; visibilityChange = "msvisibilitychange"; } else if (typeof document.webkitHidden !== "undefined") { hidden = "webkitHidden"; visibilityChange = "webkitvisibilitychange"; } var videoElement = document.getElementById("videoElement"); // If the page is hidden, pause the video; // if the page is shown, play the video function handleVisibilityChange() { if (document[hidden]) { videoElement.pause(); } else { videoElement.play(); } } // Warn if the browser doesn't support addEventListener or the Page Visibility API if (typeof document.addEventListener === "undefined" || typeof document.hidden === "undefined") { console.log("This demo requires a browser, such as Google Chrome or Firefox, that supports the Page Visibility API."); } else { // Handle page visibility change document.addEventListener(visibilityChange, handleVisibilityChange, false); // When the video pauses, set the title. // This shows the paused videoElement.addEventListener("pause", function(){ document.title = 'Paused'; }, false); // When the video plays, set the title. videoElement.addEventListener("play", function(){ document.title = 'Playing'; }, false); }
Properties overview
-
Returns
true
if the page is in a state considered to be hidden to the user, andfalse
otherwise. -
document.visibilityState
Read only -
Is a
string
denoting the visibility state of the document. Possible values:visible
: the page content may be at least partially visible. In practice this means that the page is the foreground tab of a non-minimized window.hidden
: the page content is not visible to the user. In practice this means that the document is either a background tab or part of a minimized window, or the OS screen lock is active.prerender
: the page content is being prerendered and is not visible to the user (considered hidden for purposes ofdocument.hidden
). The document may start in this state, but will never transition to it from another value. Note: browser support is optional.unloaded
: the page is being unloaded from memory. Note: browser support is optional.
//startSimulation and pauseSimulation defined elsewhere function handleVisibilityChange() { if (document.hidden) { pauseSimulation(); } else { startSimulation(); } } document.addEventListener("visibilitychange", handleVisibilityChange, false);
-
Is an
EventHandler
representing the code to be called when thevisibilitychange
event is raised.
Specifications
Specification | Status | Comment |
---|---|---|
Page Visibility (Second Edition) | Recommendation | Initial definition. |
Browser compatibility
Feature | Chrome | Firefox (Gecko) | Internet Explorer | Opera | Safari (WebKit) |
---|---|---|---|---|---|
Basic support | 13 webkit 33 |
18 (18)[2] | 10 | 12.10[1] | 7 |
onvisibilitychange |
(Yes) | 56 (56) | (Yes) | (Yes) | (Yes) |
Budget-based background timeout throttling | 57 | 58 (58) | No support | (Yes) | (Yes) |
Feature | Android | Firefox Mobile (Gecko) | IE Phone | Opera Mobile | Safari Mobile |
---|---|---|---|---|---|
Basic support | 5.0[3] | 18.0 (18)[2] | 10 | 12.10[1] | 7[4] |
onvisibilitychange |
(Yes) | 56.0 (56) | (Yes) | (Yes) | (Yes) |
Budget-based background timeout throttling | No support | 58.0 (58) | No support | (Yes) | (Yes) |
[1] Doesn't fire the visibilitychange
event when the browser window is minimized, nor set hidden
to true
.
[2] From Firefox 10 to Firefox 51 included, this property could be used prefixed with moz
.
[3] Android 4.4 supports this feature if prefixed with webkit
.
[4] From iOS 11.0.2 onwards, the values are not correct in standalone mode (when you press "Add to Homescreen") and when the screen is locked (you pressed the power button). The value for hidden
is false
and visibilityState
is visible
.
See also
- Description of the Page Visibility API on the IEBlog.
- Description of the Page Visibility API by Google