Page Visibility API sinnvoll einsetzen: Ressourcen sparen im Hintergrund-Tab
AI generated
JS
() =>
JavaScript · Browser APIs · Performance
Page Visibility API sinnvoll einsetzen
Ressourcen sparen, wenn der Tab inaktiv ist

Ein Tab im Hintergrund läuft in den meisten Anwendungen unverändert weiter, Polling-Intervalle feuern, Animationen laufen, Videos spielen unhörbar ab. Die Page Visibility API liefert mit document.hidden und dem visibilitychange-Event einen zuverlässigen Signalgeber, um genau solche Hintergrundarbeit zu drosseln und spürbar CPU, Akku und Netzwerk zu sparen, ohne dass der Nutzer etwas davon merkt.

17 Min. Lesezeit document.hidden · visibilitychange · document.visibilityState Alle modernen Browser

1. Warum Sichtbarkeit mehr ist als Fenster-Fokus

Viele Entwickler verwechseln zunächst das blur/focus-Eventpaar mit dem, was die Page Visibility API tatsächlich meldet. Ein Fenster kann den Fokus verlieren, obwohl es weiterhin sichtbar ist, etwa wenn der Nutzer in einer anderen Anwendung tippt, während der Browser daneben sichtbar bleibt. Umgekehrt kann eine Seite unsichtbar sein, ohne den Fokus zu verlieren, etwa wenn sie in einem Hintergrund-Tab liegt, während der Browser selbst im Fokus ist. Die Page Visibility API beantwortet genau die Frage, die für Ressourcenschonung relevant ist: Ist dieses Dokument gerade für den Nutzer sichtbar oder nicht.

Über die Eigenschaft document.hidden und das detailliertere document.visibilityState lässt sich diese Information synchron abfragen, das Event visibilitychange auf document informiert bei jeder Änderung. Die Page Visibility API wird ausgelöst, sobald ein Nutzer den Tab wechselt, das Fenster minimiert, zu einer anderen Anwendung wechselt oder auf mobilen Geräten die App in den Hintergrund schickt.

Der praktische Nutzen liegt darin, dass Hintergrundarbeit, die der Nutzer ohnehin nicht wahrnimmt, entsprechend gedrosselt werden kann. Ein Polling-Intervall, eine Canvas-Animation oder eine automatische Video-Wiedergabe im Hintergrund verbraucht CPU-Zyklen und Akku, ohne einen sichtbaren Mehrwert zu liefern. Die Page Visibility API macht genau diese Situationen erkennbar und steuerbar.

2. document.hidden und visibilitychange im Detail

Der einfachste Einstieg in die Page Visibility API ist die Kombination aus document.hidden als booleschem Schnappschuss und dem visibilitychange-Event für Änderungen. Zusätzlich liefert document.visibilityState einen von vier möglichen String-Werten, "visible", "hidden", oder auf einigen Plattformen auch "prerender". In der Praxis reichen für die meisten Anwendungsfälle die beiden Zustände visible und hidden vollkommen aus.

Wichtig bei der Page Visibility API ist, den aktuellen Zustand direkt beim Laden der Seite abzufragen, nicht nur auf zukünftige Änderungen zu reagieren. Wird ein Tab bereits im Hintergrund geöffnet, etwa durch einen Link, der in einem neuen Hintergrund-Tab öffnet, feuert kein initiales visibilitychange-Event, der Code muss den Startzustand also explizit prüfen.


// Track visibility state and react to changes
function watchVisibility(onVisible, onHidden) {
  // Check the initial state immediately — no event fires for it
  if (document.visibilityState === "hidden") {
    onHidden();
  } else {
    onVisible();
  }

  document.addEventListener("visibilitychange", () => {
    if (document.visibilityState === "hidden") {
      onHidden();
    } else {
      onVisible();
    }
  });
}

watchVisibility(
  () => console.log("Tab is visible — resume full activity"),
  () => console.log("Tab is hidden — throttle background work")
);

3. Polling-Intervalle drosseln statt beenden

Ein klassischer Einsatzort der Page Visibility API ist das Drosseln von Polling-Intervallen. Eine Anwendung, die alle fünf Sekunden neue Nachrichten vom Server abfragt, muss das nicht im selben Takt tun, während der Tab im Hintergrund liegt. Statt das Polling komplett zu stoppen, was bei Rückkehr zu einer sichtbaren Verzögerung führen würde, empfiehlt sich ein deutlich verlängertes Intervall im Hintergrund, etwa alle 60 statt alle 5 Sekunden.

Diese Drosselung über die Page Visibility API reduziert Server-Last und Akkuverbrauch erheblich, ohne dass Nachrichten komplett verloren gehen. Bei Rückkehr zur Sichtbarkeit lohnt sich zusätzlich ein sofortiger Poll, damit der Nutzer beim Zurückkehren zum Tab direkt aktuelle Daten sieht, statt auf das nächste reguläre Intervall warten zu müssen.


// Adaptive polling: slow down in the background, refresh instantly on return
const VISIBLE_INTERVAL_MS = 5000;
const HIDDEN_INTERVAL_MS = 60000;

let pollTimer = null;

function schedulePoll() {
  const delay = document.hidden ? HIDDEN_INTERVAL_MS : VISIBLE_INTERVAL_MS;
  pollTimer = setTimeout(async () => {
    await fetchLatestMessages();
    schedulePoll();
  }, delay);
}

document.addEventListener("visibilitychange", () => {
  if (!document.hidden) {
    // Tab became visible again — poll immediately, then resume schedule
    clearTimeout(pollTimer);
    fetchLatestMessages().then(schedulePoll);
  }
});

schedulePoll();

4. Animationen und Canvas-Rendering pausieren

Canvas-Animationen, WebGL-Szenen und JavaScript-getriebene CSS-Animationen laufen häufig über requestAnimationFrame-Schleifen, die in modernen Browsern zwar bereits automatisch auf einen sehr niedrigen Takt gedrosselt werden, sobald ein Tab verborgen ist, aber eben nicht vollständig gestoppt werden. Die Page Visibility API erlaubt eine explizite Kontrolle: Statt sich auf die implizite Drosselung des Browsers zu verlassen, pausiert die Anwendung die Schleife aktiv und spart damit auch die letzten Restzyklen.

Bei komplexen WebGL-Szenen mit vielen Partikeln oder Physik-Berechnungen macht dieser Unterschied messbar etwas aus, besonders auf Geräten mit begrenzter Akkukapazität. Die Page Visibility API in Kombination mit einem sauberen Start/Stop der requestAnimationFrame-Schleife verhindert unnötige GPU-Arbeit, die kein Nutzer je zu Gesicht bekommt.

5. Video- und Audio-Wiedergabe steuern

Für Video-Player ist die Page Visibility API ein Standardwerkzeug, um die automatische Wiedergabe zu pausieren, sobald der Tab in den Hintergrund wechselt, und sie beim Zurückkehren fortzusetzen. Anders als bei reinen Hintergrundanimationen ist hier jedoch Vorsicht geboten: Ein Nutzer möchte häufig Audio oder Podcasts im Hintergrund weiterlaufen lassen, während er in einem anderen Tab arbeitet. Ein pauschales Pausieren bei jedem visibilitychange wäre in diesem Fall kontraproduktiv.

Die richtige Lösung unterscheidet zwischen reinem Video-Content, der ohne sichtbaren Bildschirm meist keinen Sinn ergibt, und Audio-only-Inhalten, die explizit weiterlaufen sollen. Die Page Visibility API liefert dafür lediglich das Signal, die Entscheidung, was bei Unsichtbarkeit geschehen soll, bleibt Teil der Produktlogik und sollte konfigurierbar sein.


// Pause video (but not audio-only content) when the tab is hidden
const videoElement = document.querySelector("video");

document.addEventListener("visibilitychange", () => {
  if (document.hidden) {
    if (!videoElement.dataset.audioOnly) {
      videoElement.pause();
    }
  } else if (videoElement.dataset.wasPlaying === "true") {
    videoElement.play();
  }
});

videoElement.addEventListener("pause", () => {
  videoElement.dataset.wasPlaying = document.hidden ? "true" : "false";
});

6. Verweildauer korrekt messen

Analytics-Implementierungen, die "Zeit auf der Seite" messen wollen, müssen die Page Visibility API zwingend berücksichtigen, sonst zählt ein im Hintergrund vergessener Tab stundenlang mit, obwohl niemand die Seite tatsächlich betrachtet hat. Der korrekte Ansatz summiert nur die Zeitintervalle, in denen document.visibilityState auf "visible" steht, und pausiert den Zähler bei jedem Wechsel zu "hidden".

Diese Messmethode über die Page Visibility API liefert deutlich belastbarere Kennzahlen für Engagement-Analysen als eine simple Differenz zwischen Seitenaufruf und Seitenverlassen. Viele kommerzielle Analytics-Lösungen wie Google Analytics nutzen intern bereits ähnliche Mechanismen, eigene Implementierungen sollten dasselbe Prinzip konsequent anwenden.


// Track accumulated visible time, ignoring hidden intervals
let visibleSince = document.hidden ? null : Date.now();
let totalVisibleMs = 0;

document.addEventListener("visibilitychange", () => {
  const now = Date.now();

  if (document.hidden && visibleSince !== null) {
    totalVisibleMs += now - visibleSince;
    visibleSince = null;
  } else if (!document.hidden) {
    visibleSince = now;
  }
});

function getEngagementSeconds() {
  const current = visibleSince ? Date.now() - visibleSince : 0;
  return Math.round((totalVisibleMs + current) / 1000);
}

7. Zusammenspiel mit beforeunload und pagehide

Die Page Visibility API ersetzt nicht die Events rund um das Verlassen einer Seite, ergänzt sie aber sinnvoll. Auf mobilen Geräten wird eine App häufig ohne jedes unload-Event beendet, das Betriebssystem beendet den Prozess einfach, sobald Speicher benötigt wird. Der einzige verlässliche letzte Haltepunkt ist in diesem Fall der Wechsel zu document.visibilityState === "hidden", weshalb kritische Speicheroperationen, etwa das Sichern eines Formularentwurfs, an dieses Event gekoppelt werden sollten, statt an beforeunload oder unload.

Für das Senden von Analytics-Beacons beim Verlassen ist die Kombination aus visibilitychange mit Zustand hidden und der sendBeacon()-Methode das empfohlene Muster, weil beforeunload auf vielen mobilen Plattformen unzuverlässig oder gar nicht feuert. Die Page Visibility API ist damit robuster als die klassischen Unload-Events und sollte in modernen Implementierungen bevorzugt werden.

8. Fallstricke: Minimierung, Bildschirmsperre und mobile Browser

Ein häufiger Fehler beim Einsatz der Page Visibility API ist die Annahme, dass "hidden" gleichbedeutend mit "Nutzer ist weg" ist. Auf macOS bleibt ein Fenster oft als sichtbar gemeldet, selbst wenn es von anderen Fenstern vollständig überdeckt wird, weil das Betriebssystem "sichtbar" technisch als "gerendert", nicht als "im Sichtfeld" interpretiert. Für echte Aufmerksamkeitsmessung braucht man daher zusätzlich Intersection Observer oder ähnliche Signale.

Auf mobilen Geräten löst das Sperren des Bildschirms zuverlässig ein visibilitychange zu hidden aus, aber der Zeitpunkt, an dem das Betriebssystem den Tab tatsächlich pausiert oder killt, kann variieren. iOS Safari behandelt Hintergrund-Tabs deutlich aggressiver als Desktop-Chrome und kann eine Seite komplett neu laden, sobald der Nutzer zurückkehrt, wenn der Speicherdruck hoch war. Code, der auf die Page Visibility API aufbaut, sollte deshalb niemals annehmen, dass Zustand zwischen Sichtbarkeitswechseln garantiert erhalten bleibt.

9. Page Visibility API im Vergleich zu verwandten Signalen

Neben der Page Visibility API gibt es mehrere verwandte Browser-Signale, die leicht verwechselt werden. Die Wahl des richtigen Signals hängt vom genauen Anwendungsfall ab.

Signal Misst Ausgelöst durch Typischer Einsatz
Page Visibility API Tab sichtbar oder verborgen Tab-Wechsel, Minimierung, App im Hintergrund Polling drosseln, Video pausieren
focus/blur Fenster hat Tastaturfokus Klick in andere App, Alt-Tab Eingabefelder, Tastenkürzel
Intersection Observer Element im sichtbaren Viewport Scrollen, Layout-Änderung Lazy Loading, Sichtbarkeits-Tracking pro Element
pagehide/pageshow Seite verlassen oder aus BFCache zurück Navigation, Zurück-Button State-Wiederherstellung nach BFCache

In der Praxis ergänzen sich diese Signale. Die Page Visibility API ist das richtige Werkzeug für alles, was mit Tab-Sichtbarkeit im Ganzen zu tun hat, während Intersection Observer für einzelne Elemente innerhalb einer sichtbaren Seite zuständig ist. Beide zusammen ergeben ein vollständiges Bild davon, was der Nutzer gerade tatsächlich wahrnimmt.

Mironsoft

JavaScript-Entwicklung, Browser APIs und moderne Web-Anwendungen

Akkuverbrauch und CPU-Last im Hintergrund reduzieren?

Wir analysieren eure Anwendung auf unnötige Hintergrundarbeit und integrieren die Page Visibility API für gedrosseltes Polling, pausierte Animationen und korrekte Engagement-Messung.

Performance-Audit

Unnötige Hintergrundarbeit identifizieren und mit document.hidden drosseln

Media-Steuerung

Video- und Animation-Pausierung ohne ungewolltes Stoppen von Audio

Analytics-Korrektur

Verweildauer korrekt über sichtbare Zeit statt reiner Session-Dauer messen

10. Zusammenfassung

Die Page Visibility API ist ein kleines, aber wirkungsvolles Werkzeug, um Webanwendungen ressourcenschonender zu machen. Mit document.hidden, document.visibilityState und dem visibilitychange-Event lässt sich zuverlässig erkennen, ob ein Tab gerade für den Nutzer sichtbar ist, und darauf basierend Polling drosseln, Animationen pausieren und Video-Wiedergabe steuern.

Wer die Page Visibility API produktiv einsetzt, sollte den initialen Zustand beim Laden explizit prüfen, zwischen Video- und Audio-Content differenzieren, kritische Speicheroperationen an hidden statt an unload koppeln, und sich bewusst sein, dass "sichtbar" nicht zwangsläufig "im Blickfeld des Nutzers" bedeutet. In Kombination mit Intersection Observer für elementgenaue Sichtbarkeit entsteht ein vollständiges Bild der tatsächlichen Nutzeraufmerksamkeit.

Page Visibility API sinnvoll einsetzen — Das Wichtigste auf einen Blick

Kernsignal

document.hidden und visibilitychange zeigen zuverlässig, ob ein Tab gerade sichtbar ist, unabhängig vom Fenster-Fokus.

Polling und Animation

Intervalle im Hintergrund verlängern statt komplett stoppen, requestAnimationFrame-Schleifen aktiv pausieren.

Analytics

Verweildauer nur während sichtbarer Intervalle summieren, nicht während der Tab im Hintergrund liegt.

Robustheit

Kritische Speicheroperationen an hidden statt an unload koppeln, besonders auf mobilen Geräten.

11. FAQ: Page Visibility API sinnvoll einsetzen

1Was ist die Page Visibility API?
document.hidden und visibilitychange zeigen, ob ein Tab sichtbar oder verborgen ist, unabhängig vom Fenster-Fokus.
2Unterschied zu focus/blur?
focus/blur meldet Tastaturfokus, Visibility meldet Sichtbarkeit, unabhängig davon.
3Initialen Zustand prüfen?
Direkt beim Laden document.visibilityState abfragen, es feuert kein Event dafür.
4Polling komplett stoppen?
Besser verlängern statt stoppen, plus sofortiger Poll bei Rückkehr.
5Audio bei ausgeblendetem Tab?
Video meist pausieren, Audio-only in der Regel weiterlaufen lassen.
6Verweildauer korrekt messen?
Nur sichtbare Intervalle summieren, Zähler bei hidden pausieren.
7hidden statt beforeunload?
Mobile Apps enden oft ohne unload-Event, hidden ist der letzte verlässliche Punkt.
8Sichtbar heißt immer angesehen?
Nicht unbedingt, ein überdecktes Fenster kann trotzdem als sichtbar gelten.
9Unterschied zu Intersection Observer?
Visibility betrifft die ganze Seite, Intersection Observer einzelne Elemente.
10Browser-Unterstützung?
Alle modernen Browser unterstützen sie vollständig, kaum Fallback-Bedarf.