Introduction to Page Visibility API

Share this article

Mobile is cool. Mobile apps are even cooler. Unfortunately, in most cases, mobile connections suck because they are slow or you don’t haven unlimited bandwidth. It would be great to have rich web applications that don’t waste users’ resources, especially when they aren’t looking at that page. This article will show you how to partially solve this and other problems using the Page Visibility API. In the last few years, several new great APIs have been introduced to help us in our everyday work, such as Geolocation API, Navigation Timing API and Full-screen API. Page Visibility API defines a means for site developers to programmatically determine the current visibility state of the page in order to develop powerful and CPU efficient web applications. From July 26th 2012, it’s a W3C Candidate Recommendation so it’s considered stable. The first thing you might wonder is how they improve performance and save bandwidth. Imagine a situation where you have a great AJAX-based web application that send data back and forth every five seconds. If the user sends the browser tab to background when your application is running, it’ll still send data every five seconds, and also if the user takes the tab in foreground after 10 minutes. Wouldn’t it be great if the application slowed down the updates or stopped them until the user looked at the page again? Here’s where the resources optimization comes in, and where the Page Visibility API plays the key role.

How Page Visibility APIs are made

These APIs are quite simple, in fact they have a single event called visibilitychange and two read-only properties belonging to document, hidden and visibilityState. hidden is a boolean value which is true if the page is not visible, even the smallest part, and this typically happens when the tab is in background or the browser is minimized. It’s important to note that this rule has some exceptions for accessibility tools that act in full-screen mode. You can find out more on this by reading the hidden specifications. visibilityState is an enumeration that specifies the current state of the document and consists of the following values:
  • hidden: The document is not visible at all
  • visible: The document or a part of it is visible
  • prerender: The document is loaded off-screen and isn’t visible
  • unloaded: The document is going to be unloaded
Please note that the last two values, prerender and unloaded, are optional
. Besides, like the hidden attribute, the hidden value has some exceptions regarding assistive technologies.

Compatibility

Currently, there aren’t many browsers that support these APIs and those that do still use vendor prefixes. This leads to support problems because you have to manage all the prefixes to have a working code. Currently the desktop browsers that support the Page Visibility API are Chrome 13+, Internet Explorer 10, Firefox 10+, Opera beta 12.10. The mobile browsers that support the API are Chrome on Android 4.0+ and Opera Mobile 12.1+ on both Android and Symbian (source MobileHTML5.org – tested by myself on Android 4.0). A mildly annoying point is that due to the camelCase convention, if the properties are vendor prefixed, the actual property name has the first letter capitalized, while it’s lowercase if it isn’t prefixed. For the sake of clarity, let’s take the hidden property. As you can see, it starts with a lowercase letter but if it’s prefixed it starts with an uppercase “h”, so to test the support you can’t write code that resembles the following:
var browserPrefixes = ["", "webkit","moz","ms","o"];
for(var i = 0; i < browserPrefixes.length; i++) {
  if (document[browserPrefixes[i] + "hidden"] != undefined)
    // here goes the code
}
And you have to split the cases, like the following, or use some trick against strings.
// Test for unprefixed version
if (document.hidden !== undefined)
  // here goes the code
else {
  // Test for prefixed version
  var browserPrefixes = ["webkit", "moz", "ms", "o"];
  for(var i = 0; i < browserPrefixes.length; i++) {
    if (document[browserPrefixes[i] + "Hidden"] != undefined) {
      // here goes the code
    }
  }
}
As always, just like other APIs, a bunch of polyfills have been released to use those APIs in browsers that don’t support them. Some of these polyfills are visibly.js and isVis.js.

Let’s create a working example

In this section, I’ll guide you through creating a simple demo page that uses the Page Visibility API. The page will firstly test for browser support and then count the times the user actually sees the page and log its states. There are just three key functions in our demo. The first tests if the browser uses a vendor prefixed version or not, and that will be created on top of the last code shown. It will return an empty string if the browser uses the unprefixed version, the vendor prefix if it uses a prefixed version, or null
in the case that the browser doesn’t support the API.
function getPrefix() {
  var prefix = null;
  if (document.hidden !== undefined)
    prefix = "";
  else {
    var browserPrefixes = ["webkit","moz","ms","o"];
    // Test all vendor prefixes
    for(var i = 0; i < browserPrefixes.length; i++) {
      if (document[browserPrefixes[i] + "Hidden"] != undefined) {
        prefix = browserPrefixes[i];
        break;
      }
    }
  }
  return prefix;
}
The second function logs the state and increments the view count when the page is displayed.
function countView() {
  // The page is in foreground and visible
  if (document.hidden === false || document[prefix + "Hidden"] === false)
    views++;

  document.getElementById("log").innerHTML += "Your view count is: " + views + ". " + "Your page current state is: " + document[(prefix === "" ? "v" : prefix + "V") + "isibilityState"] + "
";
}
The third and last function tests whether the browser supports the API and if the test is true, it attaches a handler to the visibilitychange event, or otherwise it notifies the user. Please note that this function, too, is needed to manage the vendor prefixes.
function testPageVisibilityApi() {
  if (prefix === null)
    document.getElementById("log").innerHTML = "Your browser does not support Page Visibility API";
  else {
    document.addEventListener(prefix + "visibilitychange", countView);
    countView();
  }
}

Putting it all together

Given the functions shown in the previous section, the final and completely working code is the following.
<!DOCTYPE html>
<html>
  <head>
    <title>Page Visibility API Test Page by Aurelio De Rosa</title>
    <script>
      function getPrefix() {
        var prefix = null;
        if (document.hidden !== undefined)
          prefix = "";
        else {
          var browserPrefixes = ["webkit","moz","ms","o"];
          // Test all vendor prefixes
          for(var i = 0; i < browserPrefixes.length; i++) {
            if (document[browserPrefixes[i] + "Hidden"] != undefined) {
              prefix = browserPrefixes[i];
              break;
            }
          }
        }
        return prefix;
      }

      function countView() {
        // The page is in foreground and visible
        if (document.hidden === false || document[prefix + "Hidden"] === false)
          views++;

        document.getElementById("log").innerHTML += "Your view count is: <b>" + views +
          "</b>. " + "Your page current state is: <b>" +
          document[(prefix === "" ? "v" : prefix + "V") + "isibilityState"] + "</b><br />";
      }

      function testPageVisibilityApi() {
        if (prefix === null)
          document.getElementById("log").innerHTML = "Your browser does not support Page Visibility API";
        else {
          document.addEventListener(prefix + "visibilitychange", countView);
          countView();
        }
      }

      var views = 0;
      var prefix = getPrefix();
      window.onload = testPageVisibilityApi;
    </script>
  </head>
  <body>
    <p id="log"></p>
  </body>
</html>
Some other good examples can be found at the Mozilla Developer Network.

Conclusion

In this article, I’ve demonstrated what Page Visibility APIs are and how you can use them. The intentions of the people at W3C to help mobile devices — and not just to save resources and connectivity bandwidth — are really worthy, and I hope to see them widely used as soon as possible. As you’ve seen, the APIs are quite simple and consist of just two properties and a single event, so you can start using them within few minutes to improve your web applications. Currently, however, they aren’t really reliable due to their poor support among browsers, so you have to use a polyfill. If you’re into JavaScript APIs, check out our APIs section on the latest site on the SitePoint network … JSPro.

Frequently Asked Questions about Page Visibility API

What is the Page Visibility API and why is it important?

The Page Visibility API is a feature of modern browsers that provides an interface to query whether a web page is visible to the user or hidden in a background tab. It is important because it allows developers to optimize the performance and resource usage of their web applications. For example, a web application can pause video playback or stop fetching data when the user switches to another tab, thereby saving bandwidth and reducing CPU usage.

How does the Page Visibility API work?

The Page Visibility API works by providing a new property, document.visibilityState, which can have one of three values: ‘visible’, ‘hidden’, or ‘prerender’. The ‘visible’ state means that the page is the foreground tab of a non-minimized window. The ‘hidden’ state means that the page is a background tab or part of a minimized window, or the user has switched away from the browser. The ‘prerender’ state means that the page is being loaded off-screen and is not yet visible to the user.

How can I use the Page Visibility API in my web application?

You can use the Page Visibility API by listening for the ‘visibilitychange’ event on the document object. When this event is fired, you can check the document.visibilityState property to determine the current visibility state of the page. Based on this state, you can then pause or resume certain activities in your web application.

What are some practical use cases for the Page Visibility API?

Some practical use cases for the Page Visibility API include pausing video or audio playback when the user switches to another tab, stopping data fetches or animations to save CPU and bandwidth, and tracking user engagement by logging the amount of time the user spends on the page.

Are there any limitations or caveats with the Page Visibility API?

One limitation of the Page Visibility API is that it is not supported in all browsers. As of this writing, it is supported in all modern browsers except Internet Explorer 9 and earlier. Another caveat is that the ‘visibilitychange’ event may not be fired in certain situations, such as when the browser is minimized or the screen is locked.

Can the Page Visibility API be used with other APIs?

Yes, the Page Visibility API can be used in conjunction with other APIs to create more efficient and user-friendly web applications. For example, it can be used with the Web Audio API to pause audio playback when the user switches to another tab.

How does the Page Visibility API affect SEO?

The Page Visibility API does not directly affect SEO, but it can indirectly improve SEO by improving the user experience. By optimizing resource usage and performance, it can make your web application faster and more responsive, which can lead to higher user engagement and lower bounce rates.

Can the Page Visibility API be used in mobile browsers?

Yes, the Page Visibility API is supported in most modern mobile browsers, including Chrome for Android and Safari for iOS. However, the behavior may vary depending on the specific browser and device.

How can I test the Page Visibility API in my web application?

You can test the Page Visibility API by opening your web application in a browser, switching to another tab or minimizing the browser, and then checking whether the ‘visibilitychange’ event is fired and the document.visibilityState property is updated correctly.

Where can I find more information about the Page Visibility API?

You can find more information about the Page Visibility API in the official W3C specification, as well as in various online tutorials and articles. The Mozilla Developer Network (MDN) also provides a comprehensive guide to the API, including examples and browser compatibility information.

Aurelio De RosaAurelio De Rosa
View Author

I'm a (full-stack) web and app developer with more than 5 years' experience programming for the web using HTML, CSS, Sass, JavaScript, and PHP. I'm an expert of JavaScript and HTML5 APIs but my interests include web security, accessibility, performance, and SEO. I'm also a regular writer for several networks, speaker, and author of the books jQuery in Action, third edition and Instant jQuery Selectors.

apiHTML5 Dev CenterHTML5 Tutorials & Articles
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week