Start · Sprachen · JavaScript · Referenz · DocumentPictureInPicture.requestWindow()

DocumentPictureInPicture.requestWindow()

Methode

Öffnet ein immer im Vordergrund liegendes Picture-in-Picture-Fenster, in das beliebige HTML-Inhalte verschoben werden können, und liefert dessen <code>Window</code>-Objekt.

seit JavaScript Chrome/Edge 116+ (experimentell, nicht in Firefox/ Kategorie: webapi

Signatur

documentPictureInPicture.requestWindow(options)

Beschreibung

requestWindow() ist die zentrale Methode der Document Picture-in-Picture API. Anders als das klassische HTMLVideoElement.requestPictureInPicture(), das nur ein einzelnes Video schwebend anzeigen kann, öffnet sie ein eigenständiges, immer im Vordergrund liegendes Fenster mit einem leeren Document. In dieses Dokument kann man beliebige DOM-Elemente verschieben, zum Beispiel einen Videoplayer mit eigenen Bedienelementen, einen Videokonferenz-Bereich, einen Timer oder ein Notizfeld.

Die Methode erreicht man über das globale Objekt window.documentPictureInPicture. Sie gibt ein Promise zurück, das mit dem Window-Objekt des neuen Fensters erfüllt wird. Über pipWindow.document fügt man Inhalte ein, übernimmt Stylesheets und registriert Ereignisse, etwa pagehide, um Elemente beim Schließen zurück in die Hauptseite zu holen.

Wichtig: Der Aufruf erfordert eine vorübergehende Nutzeraktivierung, er muss also direkt aus einem Klick- oder Tastatur-Ereignis heraus erfolgen. Pro Haupt-Browsing-Kontext kann nur ein PiP-Fenster gleichzeitig existieren. Ein erneuter Aufruf ersetzt das vorhandene Fenster. Stylesheets der Ursprungsseite werden nicht automatisch übernommen, außer man nutzt die Option copyStyleSheets (sofern der Browser sie unterstützt) oder kopiert sie selbst.

Parameter

Name Typ Default Beschreibung
$options object {} Optionales Konfigurationsobjekt für das neue Fenster.
$options.width number vom Browser gewählt Gewünschte Anfangsbreite in CSS-Pixeln. Wird nur zusammen mit height berücksichtigt und kann vom Browser begrenzt werden.
$options.height number vom Browser gewählt Gewünschte Anfangshöhe in CSS-Pixeln. Wird nur zusammen mit width berücksichtigt.
$options.disallowReturnToOpener boolean false Bei true blendet der Browser die Schaltfläche „Zurück zum Tab“ im PiP-Fenster aus.
$options.preferInitialWindowPlacement boolean false Bei true öffnet sich das Fenster in Standardgröße und -position, statt sich an eine zuvor vom Nutzer gewählte Größe oder Position zu erinnern (Chrome 130+).

Rückgabewert

Typ
Promise<Window>
Beschreibung
Ein Promise, das mit dem Window-Objekt des geöffneten Picture-in-Picture-Fensters erfüllt wird. Es wird mit einer DOMException abgelehnt, zum Beispiel NotAllowedError ohne Nutzeraktivierung oder NotSupportedError in nicht unterstützten Kontexten.

Beispiele

Videoplayer in ein PiP-Fenster verschieben

const player = document.querySelector('#player');
const container = document.querySelector('#player-container');

document.querySelector('#pip-btn').addEventListener('click', async () => {
  if (!('documentPictureInPicture' in window)) {
    console.warn('Document Picture-in-Picture wird nicht unterstützt');
    return;
  }

  const pipWindow = await documentPictureInPicture.requestWindow({
    width: player.clientWidth,
    height: player.clientHeight,
  });

  // Element verschieben (nicht kopieren)
  pipWindow.document.body.append(player);

  // Beim Schließen zurück in die Hauptseite holen
  pipWindow.addEventListener('pagehide', () => {
    container.append(player);
  });
});

Stylesheets der Hauptseite übernehmen

const copyStyles = (pipWindow) => {
  [...document.styleSheets].forEach((sheet) => {
    try {
      const css = [...sheet.cssRules].map((r) => r.cssText).join('');
      const style = pipWindow.document.createElement('style');
      style.textContent = css;
      pipWindow.document.head.append(style);
    } catch {
      // Fremd-Ursprung-Stylesheet: per <link> einbinden
      const link = pipWindow.document.createElement('link');
      link.rel = 'stylesheet';
      link.href = sheet.href;
      pipWindow.document.head.append(link);
    }
  });
};

document.querySelector('#timer-pip').addEventListener('click', async () => {
  const pipWindow = await documentPictureInPicture.requestWindow({ width: 300, height: 120 });
  copyStyles(pipWindow);
  pipWindow.document.body.append(document.querySelector('#timer'));
});

Fehlerbehandlung und vorhandenes Fenster prüfen

const openPip = async () => {
  // Bereits geöffnetes Fenster wiederverwenden
  if (documentPictureInPicture.window) {
    documentPictureInPicture.window.focus();
    return documentPictureInPicture.window;
  }
  try {
    return await documentPictureInPicture.requestWindow({ disallowReturnToOpener: true });
  } catch (err) {
    console.error(`${err.name}: ${err.message}`);
  }
};

// Ohne Nutzeraktivierung schlägt der Aufruf fehl:
openPip();
NotAllowedError: Document PiP requires user activation

// Wichtig · Fallstricke

  • Browser-Unterstützung: Bisher nur in Chromium-basierten Desktop-Browsern (Chrome/Edge ab 116). Firefox und Safari unterstützen die API nicht, ebenso wenig mobile Browser. Verfügbarkeit daher immer mit 'documentPictureInPicture' in window prüfen.
  • Nur in sicheren Kontexten (HTTPS) und nur im obersten Browsing-Kontext. Aus einem iframe oder einem PiP-Fenster selbst heraus schlägt der Aufruf fehl.
  • Nutzeraktivierung erforderlich: Ohne vorausgehende Nutzerinteraktion wird das Promise mit NotAllowedError abgelehnt. Nach einem await kann die Aktivierung bereits verbraucht sein. Deshalb requestWindow() möglichst früh im Handler aufrufen.
  • width und height müssen gemeinsam angegeben werden. Wird nur einer der beiden Werte gesetzt, gibt es einen RangeError.
  • Das PiP-Fenster lässt sich nicht per Skript navigieren, und window.open() ist dort nicht möglich. Die Fenstergröße lässt sich mit resizeTo()/resizeBy() nur nach einer Nutzeraktivierung ändern.
  • Verschobene Elemente behalten ihre Ereignis-Listener. Ein <video>-Element kann beim Verschieben aber kurz stocken. Die Elemente am besten beim pagehide-Ereignis zurückverschieben, sonst gehen sie mit dem Fenster verloren.