This specification defines a means to programmatically determine the visibility state of a document. This can aid in the development of resource efficient web applications.

🚩
This document is retired and MUST NOT be used for further technical work.
See the HTML Living Standard Page Visibility section instead and raise issues in the whatwg/html repository.

Introduction

The Page Visibility API defines a means to programmatically determine the [=Document/visibility state=] of a top-level browsing context, and to be notified if the [=Document/visibility state=] changes. Without knowing the [=Document/visibility state=] of a page, web developers have been designing web pages as if they are always [=Document/visible=]. This not only results in higher machine resource utilization, but it prevents web developers from making runtime decisions based on whether the web page is [=Document/visible=] to the user. Designing web pages with knowledge of the document's [=Document/visibility state=] can result in improved user experiences and power efficient sites.

With this API, web applications can choose to alter their behavior based on whether they are [=Document/visible=] to the user or not. For example, this API can be used to scale back work when the page is no longer [=Document/visible=].

Examples of usage

To improve the user experience and optimize CPU and power efficiency the application could autoplay a video when the application is [=Document/visible=], and automatically pause the playback when the application is [=Document/hidden=]:

      const videoElement = document.getElementById("videoElement");

      // Autoplay the video if application is visible
      if (document.visibilityState === "visible") {
        videoElement.play();
      }

      // Handle page visibility change events
      function visibilityListener() {
        switch(document.visibilityState) {
          case "hidden":
            videoElement.pause();
            break;
          case "visible":
            videoElement.play();
            break;
        }
      }

      document.addEventListener("visibilitychange", visibilityListener);
      

Similar logic can be applied to intelligently pause and resume, or throttle, execution of application code such as animation loops, analytics, and other types of processing. By combining the {{Document/visibilityState}} attribute of the {{Document}} interface and the `"visibilitychange"` event, the application is able to both query and listen to page visibility events to deliver a better user experience, as well as improve efficiency and performance of its execution.

Visibility states

The [=document=] of the top-level browsing context can be in one of the following visibility states:

hidden

The [=document=] is not [=Document/visible=] at all on any screen, as determined by running the steps to [=determine the visibility state=] of the [=document=]'s [=relevant global object=]'s [=browsing context=].

visible
The [=document=] is at least partially visible on at least one screen, as determined by running the steps to [=determine the visibility state=] of the [=document=]'s [=relevant global object=]'s [=browsing context=].

The [=Document/visibility states=] are reflected in the API via the {{VisibilityState}} enum.

The steps to determine the visibility state of a [=browsing context=] |context| are as follows. The steps return a [=Document/visibility state=].

  1. Let |doc:Document| be the |context|'s [=top-level browsing context=]'s [=active document=].
  2. Assert: |doc| is a [=Document=].
  3. Return [=Document/visible=] if:
    • The user agent has assistive technologies attached to the |doc|.
    • Any of the |doc|'s viewport contents are visible to the user.
  4. Otherwise, return [=Document/hidden=].

VisibilityState enum

      enum VisibilityState {
        "hidden", "visible"
      };
      

The VisibilityState enum is used to represent the [=Document/visibility states=].

The "hidden" enum value represents the [=Document/hidden=] [=Document/visibility state=].

Likewise, the "visible" enum value represents the [=Document/visible=] [=Document/visibility state=].

Extensions to the `Document` interface

This specification extends the {{Document}} interface:

      partial interface Document {
        readonly attribute boolean hidden;
        readonly attribute VisibilityState visibilityState;
        attribute EventHandler onvisibilitychange;
      };
      

hidden attribute

On getting, the {{Document/hidden}} attribute MUST:

  1. Let |state:Visibility State| be the result of [=determine the visibility state=] of [=this=]'s [=relevant global object=]'s [=browsing context=].
  2. If |state| is [=Document/visible=], then return false. Return true otherwise.

visibilityState attribute

On getting, the {{Document/visibilityState}} attribute the user agent MUST:

  1. Let |state:Visibility State| be the result of [=determine the visibility state=] of [=this=]'s [=relevant global object=]'s [=browsing context=].
  2. If |state| is [=Document/visible=], return {{VisibilityState/"visible"}}. Otherwise, return {{VisibilityState/"hidden"}}.

onvisibilitychange event handler attribute

The {{Document/onvisibilitychange}} attribute is an event handler IDL attribute for the `"visibilitychange"` event type (see [[[#reacting-to-visibilitychange]]]).

Reacting to `"visibilitychange"` changes

The task source for these tasks is the user interaction task source.

When the user agent determines that the visibility of the {{Document}} of the top-level browsing context has changed, the user agent MUST run the following steps:

  1. Let |doc:Document| be the {{Document}} of the top-level browsing context.
  2. If |doc| is now [=Document/visible=]:
    1. If traversing to a session history entry, run the now visible algorithm before running the step to fire the [=Window/pageshow=] event.
    2. Otherwise, queue a task that runs the now visible algorithm.
  3. Else if |doc| is now not [=Document/visible=], or if the user agent is to [=Window/unload=] |doc|:
    1. If the user agent is to [=Window/unload=] the {{Document}}, run the now hidden algorithm during the unloading document visibility change steps.
    2. Otherwise, queue a task that runs the now hidden algorithm.

The now visible algorithm runs the following steps synchronously:

  1. Let |doc:Document| be the {{Document}} of the top-level browsing context.
  2. Fire an event named "`visibilitychange`" that bubbles, isn't cancelable, and has no default action, at the |doc|.
  3. Run external now visible algorithm if one is defined by another specification.

The now hidden algorithm runs the following steps synchronously:

  1. Let |doc:Document| be the {{Document}} of the top-level browsing context.
  2. Fire an event named "`visibilitychange`" that bubbles, isn't cancelable, and has no default action, at the |doc|.
  3. Run external now hidden algorithm if one is defined by another specification.

Privacy and Security

The Page Visibility API enables developers to know when a {{Document}} is visible or in focus. Existing mechanisms, such as the [=Window/focus=] and [=Window/blur=] events, when attached to the {{Window}} object already provide a mechanism to detect when the {{Document}} is the active document; the [=Window/unload=] event provides a notification that the page is being unloaded.

Accessibility considerations

To accommodate assistive technologies that are typically full screen but still show a view of the page, when applicable, on getting, the {{Document/visibilityState}} attribute MAY return {{VisibilityState/"visible"}}, instead of {{VisibilityState/"hidden"}}, when the user agent is not minimized but is fully obscured by other applications.

Terminology

The following concepts and interfaces are defined in the [[!HTML]] specification:

Acknowledgments

Thanks to Alex Komoroske, Arvind Jain, Boris Zbarsky, Cameron McCormack, James Robinson, Jason Weber, Jonas Sicking, Karen Anderson, Kyle Simpson, Nat Duca, Nic Jansma, Philippe Le Hegaret, and Todd Reifsteck for their contributions to this work.