Detect When a Page Isn’t Visible (Page Visibility API)

This page demonstrates how to detect when a browser tab or window loses focus and when it returns. Use this to pause timers, throttle animations, autosave drafts, or nudge users back to your app.

Try the Demo

Switch to another tab or minimise this window, then come back. Each change in visibility is logged below, and the title temporarily changes to “Come Back!” when the page is hidden.

You’ve been away, haven’t you!


	

Description

The Page Visibility API fires events whenever a document becomes hidden (e.g., user switches tabs, locks the device, or minimises the window) or visible again. This enables experience-aware behaviour such as pausing non‑critical work when the user isn’t looking, and resuming or refreshing when they return.

On this page, each visibility change is timestamped below. When the page is hidden, a brief message is prepared for the user’s return and the document title changes to “Come Back!”. When the page becomes visible again, the message fades out.

Further Uses and Ideas

Limitations

Note: Historically, Chrome on iOS did not always detect a tab hidden behind another tab, though it did detect the app being minimised or replaced by another app.

How It Works

Below is a self‑contained snippet (HTML, CSS, and JavaScript) that logs visibility changes, updates the page title, and shows a small “welcome back” message when focus returns.

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>Page Visibility API</title>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
  <script>
  var visibilityChange = (function (window) {
    var inView = false;
    return function (fn) {
      window.onfocus = window.onblur = window.onpageshow = window.onpagehide = function (e) {
        if ({focus:1, pageshow:1}[e.type]) {
          if (inView) return;
          fn("visible");
          inView = true;
        } else if (inView) {
          fn("hidden");
          inView = false;
        }
      };
    };
  }(this));

  visibilityChange(function (state) {
    var d = new Date();
    var n = d.toLocaleTimeString();
    var out = document.getElementById("textoutput");
    out.innerHTML = n + ": Page is " + state + "<br>" + out.innerHTML;

    if (state === "hidden") {
      $("#message").stop(true, true).fadeIn();
      document.title = "Come Back!";
    }
    if (state === "visible") {
      $("#message").stop(true, true).fadeOut(2000);
      document.title = "Page Visibility API";
    }
  });
  </script>

  <style>
    body { font-family: system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; }
    #message { display: none; text-align: center; margin: 1rem 0; }
    #textoutput { height: 200px; overflow: auto; border: 1px solid #e5e7eb; padding: .75rem; border-radius: .5rem; background: #fafafa; }
    pre code { display:block; background:#0f172a; color:#e2e8f0; padding:1rem; border-radius:.5rem; overflow:auto; }
  </style>
</head>
<body>
  <h1>Page Visibility API</h1>
  <div id="message" aria-live="polite"><h2>Welcome back — we missed you!</h2></div>
  <div id="textoutput"></div>
</body>
</html>

Relevant Links

Read more on MDN: Page Visibility API

Version History

Version Date Changes
1.1 20th August 2025 Copy updates, added clearer demo instructions, improved accessibility notes.
1.0 10th November 2016 Initial demo and documentation.

Comments For This Page

Agreed that Chrome on iOS does not detect a tabbed session being hidden behind another tab. It does detect the Chrome app being minimised or overridden by another app. We will add a Limitations section to record this.

By Daft Logic on 14th November 2019

Not working on iOS Chrome iPhone

By Yaroslav on 14th November 2019

You should try to open a new tab, go to it and return and check out what happens to it next.

By Nobody on 6th February 2019

Add Your Comment

There's no need to create an account or provide unnecessary details. Just your comment.