JavaScript Document visibilitychange Event

Beginner
⏱️ 12 min read
📚 Updated: Jul 2026
🎯 5 Examples
🚀 5 Try-it labs
Document event
Baseline Widely available

What You’ll Learn

The Document visibilitychange event fires when the page’s visibility status changes—for example when the user switches tabs, minimizes the browser, or (on mobile) leaves the app. Learn to read document.visibilityState and document.hidden, and practice with five try-it labs.

01

Kind

Document event

02

Type

Event (generic)

03

Cancelable

No

04

Read

visibilityState

05

API

Page Visibility

06

Status

Baseline · Widely available

Introduction

A page can be open but not what the user is looking at—another tab is focused, the window is minimized, or the phone switched to a different app. The Page Visibility API reports that with document.visibilityState and document.hidden.

Whenever that status changes, Document visibilitychange fires. The Event object itself does not include the new state; you read document.visibilityState (or document.hidden) inside the handler.

💡
Beginner tip

Transitioning to hidden is often the last reliable signal before a tab goes away. MDN recommends treating it as a likely end of the session for analytics (for example with navigator.sendBeacon)—prefer this over relying only on unload / beforeunload.

Understanding Document visibilitychange

A standard Document event that answers: “Did this page just become visible or hidden to the user?”

  • Fires when the document’s visibility status changes (MDN).
  • Triggers include switching tabs, navigating away, minimizing/closing the browser, or switching apps on mobile.
  • Not cancelable.
  • Event type — a generic Event.
  • Handlerdocument.onvisibilitychange or addEventListener("visibilitychange", ...).
  • Status — Baseline Widely available since April 2021 (MDN).

📝 Syntax

Use the event name with addEventListener, or set the handler property:

JavaScript
addEventListener("visibilitychange", (event) => { });

onvisibilitychange = (event) => { };

Event type

A generic Event. The event is not cancelable.

Read the visibility status

JavaScript
document.addEventListener("visibilitychange", () => {
  console.log(document.visibilityState); // "visible" or "hidden"
  console.log(document.hidden);          // true when hidden
});

visibilityState values (beginner view)

ValueMeaning
visibleThe page content may be visible to the user
hiddenThe page is not visible (background tab, minimized, etc.)

⚖️ visibilitychange vs unload / blur

Topicvisibilitychangeunload / beforeunloadWindow blur
MeansPage visibility changedPage may be leaving / unloadingWindow lost focus
Tab switchYes — becomes hiddenOften unreliableMay fire, but not the Page Visibility API
Read statevisibilityState / hiddenN/ANot the same as visibility
Analytics tipPrefer hidden + sendBeaconAvoid as only signalNot ideal for session end
MDN guidancePage Visibility APILess reliable for modern browsersFocus, not visibility

⚡ Quick Reference

GoalCode / note
Listendocument.addEventListener("visibilitychange", fn)
Handler propertydocument.onvisibilitychange = fn
Current statedocument.visibilityState
Boolean helperdocument.hidden (true when not visible)
Pause work when hiddenif (document.hidden) { /* pause */ }
End-of-session logOn hidden, call navigator.sendBeacon(...)
MDN statusBaseline Widely available (Apr 2021)

🔍 At a Glance

Four facts to remember about Document visibilitychange.

Event type
Event

No state on event

Means
Visibility changed

Tab / app focus

Read with
visibilityState

Or document.hidden

Baseline
yes

Widely available

Examples Gallery

Examples follow MDN Document: visibilitychange event. In try-it labs, switch away from the tab (or minimize) then come back to see hiddenvisible updates.

📚 Getting Started

Log visibility changes with both listener styles.

Example 1 — Log visibilityState

Print the current state whenever visibility changes.

JavaScript
const log = document.getElementById("log");

document.addEventListener("visibilitychange", () => {
  log.textContent +=
    "visibilityState: " + document.visibilityState + "\n";
});
Try It Yourself

How It Works

The Event has no visibility payload. Always read document.visibilityState inside the handler.

Example 2 — document.onvisibilitychange

Use the handler property and show a one-line status.

JavaScript
const out = document.getElementById("out");

document.onvisibilitychange = () => {
  out.textContent =
    "Now: " + document.visibilityState +
    " (hidden=" + document.hidden + ")";
};

out.textContent =
  "Now: " + document.visibilityState +
  " (hidden=" + document.hidden + ")";
Try It Yourself

How It Works

Showing the current state once on startup covers the case where no change has fired yet. Prefer addEventListener for multiple listeners.

📈 Pause, Beacon & Panel

MDN-style pause/resume, analytics on hidden, and a live status panel.

Example 3 — Pause a Timer When Hidden

Stop UI updates in the background; resume when visible again (MDN pause pattern).

JavaScript
const out = document.getElementById("out");
let ticks = 0;
let timer = null;

function start() {
  if (timer) return;
  timer = setInterval(() => {
    ticks += 1;
    out.textContent = "Ticks: " + ticks + " (" + document.visibilityState + ")";
  }, 500);
}

function stop() {
  clearInterval(timer);
  timer = null;
}

document.addEventListener("visibilitychange", () => {
  if (document.hidden) {
    stop();
  } else {
    start();
  }
});

start();
Try It Yourself

How It Works

Same idea as MDN’s audio pause example: use document.hidden to stop background work the user does not need while the page is hidden.

Example 4 — Analytics on hidden (MDN)

Treat hidden as end-of-session and call sendBeacon.

JavaScript
const out = document.getElementById("out");
const analyticsData = "session=demo&action=leave";

document.onvisibilitychange = () => {
  if (document.visibilityState === "hidden") {
    // Real apps: navigator.sendBeacon("/log", analyticsData);
    out.textContent =
      "Would sendBeacon with: " + analyticsData +
      " at " + new Date().toLocaleTimeString();
  } else {
    out.textContent = "Visible again — session continuing";
  }
};
Try It Yourself

How It Works

Matches MDN’s analytics example. Labs log instead of posting to a real /log endpoint so the try-it stays self-contained.

Example 5 — Live Visibility Panel

Show a badge that flips between visible and hidden.

JavaScript
const badge = document.getElementById("badge");
const detail = document.getElementById("detail");

function render() {
  const state = document.visibilityState;
  badge.textContent = state.toUpperCase();
  badge.dataset.state = state;
  detail.textContent =
    "document.hidden = " + document.hidden +
    " · updated " + new Date().toLocaleTimeString();
}

document.addEventListener("visibilitychange", render);
render();
Try It Yourself

How It Works

Calling render() once at startup shows the initial state; the listener keeps the panel in sync after tab switches.

🚀 Common Use Cases

  • Pausing video, audio, or animations when the tab is hidden.
  • Stopping polling / WebSocket chatter in the background.
  • Sending analytics with sendBeacon on transition to hidden.
  • Saving draft state before the user leaves the page.
  • Resuming work only when visibilityState becomes visible again.

🔧 How It Works

1

User leaves or returns

Tab switch, minimize, navigate away, or switch apps on mobile.

user action
2

visibilityState updates

The Document moves between visible and hidden.

Page Visibility
3

visibilitychange fires

A generic Event arrives on the Document (not cancelable).

event
4

You pause, save, or resume

Read visibilityState / hidden and react.

📝 Notes

Universal Browser Support

Document visibilitychange is marked Baseline Widely available on MDN (since April 2021). Logos use the shared browser-image-sprite.png sprite from this project. Pair it with document.visibilityState and document.hidden.

Baseline · Widely available

Document visibilitychange

Fires when the document visibility status changes. Read visibilityState or hidden inside the handler.

Universal Widely available
Google Chrome Full support · Desktop & Mobile
Full support
Mozilla Firefox Full support · Desktop & Mobile
Full support
Apple Safari Full support · macOS & iOS
Full support
Microsoft Edge Full support · Chromium Edge
Full support
Opera Full support · Modern versions
Full support
Internet Explorer Legacy Page Visibility support in older IE; prefer modern browsers
Legacy
visibilitychange Excellent

Bottom line: Listen on document for visibilitychange, read visibilityState/hidden, pause background work when hidden, and use sendBeacon for leave analytics.

Conclusion

Document visibilitychange is the Page Visibility signal that the user left or returned to your page. Read document.visibilityState (or document.hidden) in the handler to pause work, save state, or send analytics.

Continue with scrollingElement, visibilityState, or the JavaScript hub.

💡 Best Practices

✅ Do

  • Read visibilityState or hidden in the handler
  • Pause media / timers when hidden
  • Use sendBeacon on transition to hidden for leave logs
  • Resume carefully when becoming visible again
  • Prefer this API over unload-only session end

❌ Don’t

  • Expect the Event object to include the new state string
  • Keep heavy polling running while the tab is hidden
  • Treat Window blur as the same as Page Visibility
  • Rely only on beforeunload for analytics
  • Call this Experimental—it is Baseline Widely available

Key Takeaways

Knowledge Unlocked

Five things to remember about visibilitychange

Visibility changed — read visibilityState or hidden.

5
Core concepts
🔍 02

Read properties

visibilityState / hidden

API
⏸️ 03

Pause when hidden

Stop background UI work

Pattern
📡 04

Beacon on leave

sendBeacon + hidden

Analytics
05

Baseline ready

Widely available

Status

❓ Frequently Asked Questions

What is the Document visibilitychange event?

It fires when the document visibility status changes—for example when the user switches tabs, navigates away, minimizes the browser, or switches apps on mobile.

Is visibilitychange deprecated or experimental?

No. MDN marks Document visibilitychange as Baseline Widely available (since April 2021). It is not Deprecated, Experimental, or Non-standard.

How do I know if the page is hidden?

Inside the handler, read document.visibilityState ("visible" or "hidden") or document.hidden (true when not visible). The Event object does not include the new state.

Is the event cancelable?

No. MDN states visibilitychange is not cancelable.

Why use it instead of unload?

Transitioning to hidden is often the last reliably observable event. MDN recommends it for end-of-session analytics (for example with navigator.sendBeacon) instead of relying only on unload/beforeunload.

Is there an onvisibilitychange property?

Yes. You can use document.onvisibilitychange or document.addEventListener("visibilitychange", ...).

Did you know?

Transitioning to hidden is often the last event that is reliably observable by the page—which is why MDN recommends it for end-of-session analytics instead of depending only on unload.

Next: Document scrollingElement

Learn which Element is the scrolling root of the document.

scrollingElement →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

5 people found this page helpful