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.
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.
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.
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.
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>
Read more on MDN: Page Visibility API
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. |
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 2019Not working on iOS Chrome iPhone
By Yaroslav on 14th November 2019You 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 2019There's no need to create an account or provide unnecessary details. Just your comment.