Start · Sprachen · JavaScript · Referenz · Document.visibilityState

Document.visibilityState

Eigenschaft

Die schreibgeschützte Eigenschaft <code>document.visibilityState</code> gibt als String an, ob das Dokument gerade sichtbar (<code>"visible"</code>) oder verborgen (<code>"hidden"</code>) ist.

seit JavaScript Baseline: alle modernen Browser (seit 2015) Kategorie: webapi

Signatur

Document.visibilityState

Beschreibung

document.visibilityState ist Teil der Page Visibility API. Die Eigenschaft sagt dir, ob der Inhalt der Seite für den Nutzer gerade sichtbar ist. Sie ist "hidden", wenn der Tab im Hintergrund liegt, das Fenster minimiert ist, der Bildschirm gesperrt ist oder das Betriebssystem die Seite ausblendet. Sonst ist sie "visible".

Brauchbar ist das vor allem, um Ressourcen zu sparen und das Verhalten an die Situation anzupassen. Typische Fälle sind: Polling oder Animationen anhalten, Videos oder Audio pausieren, Analytics-Sitzungen beenden oder Daten ein letztes Mal sichern, bevor ein mobiler Browser die Seite einfriert oder beendet.

Normalerweise liest man den Wert im Handler des Events visibilitychange. Dieses Event wird auf document ausgelöst, sobald sich visibilityState ändert. Du kannst es mit document.addEventListener("visibilitychange", handler) abonnieren oder über document.onvisibilitychange setzen.

Mögliche Werte:

  • "visible": Die Seite ist zumindest teilweise sichtbar, liegt also im Vordergrund-Tab eines nicht minimierten Fensters.
  • "hidden": Die Seite ist für den Nutzer nicht sichtbar.
  • "prerender" (veraltet): Früher gab es diesen Wert für vorab gerenderte Seiten. Er ist aus der Spezifikation entfernt, und moderne Browser liefern ihn nicht mehr.

Rückgabewert

Typ
"visible" | "hidden"
Beschreibung
Ein String mit dem aktuellen Sichtbarkeitszustand des Dokuments. Die Eigenschaft ist schreibgeschützt.

Beispiele

Aktuellen Zustand abfragen

// Beim Laden prüfen, ob die Seite sichtbar ist
console.log(`Sichtbarkeit: ${document.visibilityState}`);

if (document.visibilityState === "hidden") {
  console.log("Seite wurde im Hintergrund geöffnet");
}
Sichtbarkeit: visible

Video pausieren, wenn der Tab verborgen wird

const video = document.querySelector("video");

const handleVisibility = () => {
  if (document.visibilityState === "hidden") {
    video.pause();
  } else {
    video.play().catch(() => {
      // Autoplay kann vom Browser blockiert werden
    });
  }
};

document.addEventListener("visibilitychange", handleVisibility);

// Später aufräumen, z. B. beim Verlassen einer SPA-Ansicht
// document.removeEventListener("visibilitychange", handleVisibility);

Polling nur im sichtbaren Zustand

let timerId = null;

const fetchUpdates = async () => {
  const res = await fetch("/api/updates");
  const data = await res.json();
  console.log("Neue Daten:", data);
};

const startPolling = () => {
  if (timerId === null) timerId = setInterval(fetchUpdates, 10_000);
};

const stopPolling = () => {
  clearInterval(timerId);
  timerId = null;
};

document.onvisibilitychange = () => {
  document.visibilityState === "visible" ? startPolling() : stopPolling();
};

if (document.visibilityState === "visible") startPolling();

Analytics-Daten beim Verbergen zuverlässig senden

const sessionStart = performance.now();

document.addEventListener("visibilitychange", () => {
  if (document.visibilityState === "hidden") {
    const payload = JSON.stringify({
      dauerMs: Math.round(performance.now() - sessionStart),
    });
    // sendBeacon funktioniert auch, wenn die Seite gleich entladen wird
    navigator.sendBeacon("/analytics", payload);
  }
});

// Wichtig · Fallstricke

  • Anstelle von unload/beforeunload: Auf Mobilgeräten werden unload-Events oft gar nicht ausgelöst. Der Wechsel auf "hidden" ist in vielen Fällen der letzte Moment, auf den man sich verlassen kann, um Daten zu sichern oder per navigator.sendBeacon() zu senden.
  • Nicht gleich Fokus: Eine Seite kann "visible" sein, ohne den Fokus zu haben, etwa wenn ein anderes Fenster darüber liegt, sie aber nicht ganz verdeckt. Den Fokus prüfst du mit document.hasFocus() bzw. den Events focus/blur.
  • Verdeckte Fenster: Ob ein Fenster, das von anderen Fenstern vollständig verdeckt ist, als "hidden" gilt, hängt von Browser und Betriebssystem ab.
  • "prerender" ist veraltet: Prüfe Bedingungen immer ausdrücklich auf === "visible" bzw. === "hidden".
  • Timer im Hintergrund: Browser drosseln setTimeout/setInterval in verborgenen Tabs ohnehin stark, und requestAnimationFrame läuft dort gar nicht. Verlass dich also nicht auf genaues Timing im Zustand "hidden".
  • Kompatibilität: Wird von allen modernen Browsern ohne Präfix unterstützt. Sehr alte Versionen (vor ca. 2013) kannten nur Varianten mit Präfix wie webkitVisibilityState. Die ältere Eigenschaft document.hidden ist ein boolesches Gegenstück.