Back

So erkennen Sie, wann ein Browser-Tab inaktiv wird

So erkennen Sie, wann ein Browser-Tab inaktiv wird

Sie haben ein Polling-Intervall, das alle zehn Sekunden ausgelöst wird, ein Video, das im Hintergrund läuft, oder eine Animationsschleife — und all das verbraucht Ressourcen für einen Nutzer, der vor fünf Minuten den Tab gewechselt hat. Die Lösung ist denkbar einfach, sobald man die richtige API kennt.

Wichtige Erkenntnisse

  • Die Page Visibility API ist der moderne und zuverlässige Weg, um Sichtbarkeitsänderungen von Tabs zu erkennen, und ersetzt ältere Ansätze mit window.onfocus und window.onblur.
  • Verwenden Sie document.hidden oder document.visibilityState zusammen mit dem visibilitychange-Event, um zu reagieren, wenn ein Tab inaktiv oder aktiv wird.
  • Praktische Anwendungen umfassen das Pausieren von Polling, das Anhalten der Medienwiedergabe, das automatische Speichern von Formularentwürfen und das Senden von Analytics am Sitzungsende.
  • Kombinieren Sie visibilitychange mit pagehide und navigator.sendBeacon() für ein zuverlässiges Session-End-Tracking und vermeiden Sie das unload-Event, da es den Back-/Forward-Cache beschädigt.
  • Entfernen Sie Listener immer beim Abbau von Komponenten in Single-Page-Anwendungen, um Memory Leaks zu vermeiden.

Das richtige Werkzeug: Die Page Visibility API

Ältere Lösungen basierten auf den Focus- und Blur-Events des window-Objekts — window.onfocus und window.onblur. Diese erkennen, ob das Browserfenster den Tastaturfokus besitzt, nicht aber, ob der Tab tatsächlich sichtbar ist. Bei Split-Screen-Setups oder Multi-Window-Workflows kann ein Tab vollständig sichtbar sein, ohne den Fokus zu haben, und umgekehrt. Außerdem verhielten sie sich speziell beim Tab-Wechsel browserübergreifend inkonsistent.

Die Page Visibility API löst dieses Problem sauber. Sie sagt Ihnen exakt, ob die Seite für den Nutzer sichtbar ist, unabhängig vom Fokuszustand.

Zwei Eigenschaften liefern Ihnen den aktuellen Status:

  • document.visibilityState — gibt "visible" oder "hidden" zurück
  • document.hidden — gibt true zurück, wenn der Tab verborgen ist, und false, wenn er sichtbar ist

In modernen Browsern sind keine Vendor-Präfixe mehr erforderlich. Die API wird von Chrome, Firefox, Safari und Edge umfassend unterstützt — sowohl auf Desktop als auch auf mobilen Geräten.

Auf das visibilitychange-Event hören

Das visibilitychange-Event wird auf document ausgelöst, wann immer der Tab verborgen oder wieder sichtbar wird. Hier ist das Grundmuster:

document.addEventListener("visibilitychange", () => {
  if (document.hidden) {
    console.log("Tab is hidden — pause or reduce work");
  } else {
    console.log("Tab is visible — resume work");
  }
});

Sie können document.visibilityState auch direkt auslesen, falls Sie den String-Wert anstelle eines Booleans benötigen.

Praktische Anwendungsfälle

Polling pausieren und fortsetzen

Anstatt API-Anfragen zu stellen, während sich der Nutzer in einem anderen Tab befindet, pausieren Sie das Intervall und nehmen es wieder auf, wenn er zurückkehrt:

let intervalId = null;

function startPolling() {
  if (intervalId !== null) return;
  intervalId = setInterval(fetchData, 10000);
}

function stopPolling() {
  clearInterval(intervalId);
  intervalId = null;
}

document.addEventListener("visibilitychange", () => {
  document.hidden ? stopPolling() : startPolling();
});

startPolling();

Hinweis: Browser drosseln setInterval in Hintergrund-Tabs, anstatt es vollständig anzuhalten, weshalb die Zeitgenauigkeit in verborgenen Tabs ohnehin unzuverlässig ist. Explizites Pausieren ist sauberer. Die Absicherung gegen doppelte Intervalle verhindert zudem, dass sich mehrere Timer stapeln, falls startPolling jemals zweimal aufgerufen wird.

Medienwiedergabe pausieren

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

document.addEventListener("visibilitychange", () => {
  if (document.hidden) {
    video.pause();
  } else {
    video.play().catch(() => {
      // Autoplay may be blocked by the browser; handle silently
    });
  }
});

Der .catch()-Handler ist wichtig, weil video.play() ein Promise zurückgibt, das abgelehnt werden kann, wenn der Browser Autoplay blockiert — andernfalls würde ein nicht abgefangener Fehler geworfen.

Automatisches Speichern eines Formularentwurfs

Lösen Sie ein Speichern aus, wenn der Nutzer den Tab verlässt, anstatt auf einen festen Timer zu setzen:

document.addEventListener("visibilitychange", () => {
  if (document.hidden) {
    saveDraft();
  }
});

Analytics senden, bevor der Nutzer geht

Für Daten am Sitzungsende kombinieren Sie das visibilitychange-Event mit pagehide und verwenden Sie navigator.sendBeacon(), um Daten zuverlässig zu senden, ohne die Navigation zu blockieren:

document.addEventListener("visibilitychange", () => {
  if (document.visibilityState === "hidden") {
    navigator.sendBeacon(
      "/analytics",
      JSON.stringify({ event: "tab_hidden" })
    );
  }
});

window.addEventListener("pagehide", () => {
  navigator.sendBeacon(
    "/analytics",
    JSON.stringify({ event: "page_unload" })
  );
});

Vermeiden Sie für diesen Zweck das unload-Event — es ist in modernen Browsern unzuverlässig und bricht den Back-/Forward-Cache (bfcache), was die Navigationsleistung beeinträchtigt. In mobilen Browsern ist visibilitychange mit dem Status "hidden" oft das einzige zuverlässige Signal dafür, dass eine Sitzung beendet wurde, da pagehide und beforeunload nicht immer ausgelöst werden.

Event-Listener aufräumen

Entfernen Sie Listener immer, wenn sie nicht mehr benötigt werden, insbesondere in Single-Page-Anwendungen:

function handleVisibility() {
  console.log(document.visibilityState);
}

document.addEventListener("visibilitychange", handleVisibility);

// Later, when tearing down:
document.removeEventListener("visibilitychange", handleVisibility);

Denken Sie daran, dass die an removeEventListener übergebene Referenz exakt dieselbe Funktionsreferenz sein muss, die in addEventListener verwendet wurde. Inline-Arrow-Funktionen können nicht entfernt werden, da jede eine neue Referenz erzeugt.

Fazit

Die Page Visibility API — konkret document.hidden, document.visibilityState und das visibilitychange-Event — ist der korrekte, moderne Weg, um zu erkennen, wann ein Browser-Tab inaktiv wird. Sie funktioniert zuverlässig in allen aktuellen Browsern, behandelt Tab-Wechsel akkurat dort, wo die Focus- und Blur-Events von window versagen, und lässt sich gut mit navigator.sendBeacon() und dem pagehide-Event für die Behandlung des Sitzungsendes kombinieren. Nutzen Sie sie, um unnötige Arbeit zu stoppen, Zustände zu speichern oder Engagement zu erfassen — und räumen Sie Ihre Listener auf, wenn Sie fertig sind.

FAQs

Beide geben an, ob die Seite sichtbar ist, aber sie liefern unterschiedliche Typen. document.hidden gibt einen Boolean zurück, was für schnelle bedingte Prüfungen praktisch ist. document.visibilityState gibt einen String zurück, derzeit entweder visible oder hidden, was aussagekräftiger und zukunftssicher ist, falls später weitere Zustände hinzukommen. Verwenden Sie das, was am besten zu Ihrem Code-Stil passt.

Browser drosseln Hintergrund-Timer, anstatt sie zu stoppen, und begrenzen sie typischerweise auf einmal pro Sekunde oder seltener. Das Intervall läuft weiter, aber mit unvorhersehbaren Raten, sodass zeitkritische Logik unzuverlässig wird. Die sauberste Lösung ist, clearInterval innerhalb Ihres visibilitychange-Handlers aufzurufen und das Intervall neu zu starten, wenn der Tab wieder sichtbar wird.

Bevorzugen Sie visibilitychange in Kombination mit pagehide und navigator.sendBeacon. Die Events beforeunload und unload sind auf mobilen Geräten unzuverlässig und brechen den Back-/Forward-Cache, was die Performance beeinträchtigt. Das visibilitychange-Event mit Status hidden ist das konsistenteste Signal über Desktop- und mobile Browser hinweg, um zu erkennen, dass ein Nutzer die Seite verlassen hat.

Ja, aber das Verhalten hängt vom Elternelement ab. Ein iframe erbt in der Regel den Sichtbarkeitsstatus seines übergeordneten Dokuments. Das Ausblenden des iframes selbst per CSS, etwa mit `display: none`, löst keine `visibilitychange`-Events innerhalb des iframes aus. Jedes iframe hat sein eigenes document-Objekt, sodass Sie auf visibilitychange am iframe-Dokument lauschen, nicht am Top-Window.

Understand every bug

Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay