Start · Sprachen · JavaScript · Referenz · Viewport

Viewport

Schnittstelle

Stellt das Viewport des Geräts dar und liefert über <code>segments</code> die Position und Größe der einzelnen Viewport-Segmente auf faltbaren Geräten oder Geräten mit zwei Bildschirmen.

seit JavaScript Experimentell: Chromium 138+ (Chrome, Edge); nicht Kategorie: webapi

Signatur

interface Viewport

Beschreibung

Das Interface Viewport gehört zur Viewport Segments API. Eine Instanz erhält man über window.viewport. Einen Konstruktor gibt es nicht. Die API ist für faltbare Geräte und Geräte mit zwei Bildschirmen gedacht (z. B. Samsung Galaxy Z Fold oder Microsoft Surface Duo). Dort ist der sichtbare Bereich durch ein Scharnier oder eine Falz in mehrere logische Bereiche geteilt, die sogenannten Segmente.

Die einzige Eigenschaft ist Viewport.segments. Sie ist schreibgeschützt und liefert ein Array von DOMRect-Objekten. Jedes Objekt beschreibt Position (x, y) und Größe (width, height) eines Segments in CSS-Pixeln, relativ zum Layout-Viewport. Ist das Viewport nicht geteilt, enthält das Array genau ein Segment. In eingebetteten Frames (iframe) wird null zurückgegeben.

Die API nutzt man, wenn JavaScript das Layout an die Falz anpassen soll. Beispiele: eine Kartenansicht links und Details rechts, ein Video oben und die Steuerung unten, oder ein Dialog, der nicht über das Scharnier hinweg angezeigt werden soll. Für reine Layout-Aufgaben reicht oft CSS: Die Media Features horizontal-viewport-segments und vertical-viewport-segments sowie die Umgebungsvariablen env(viewport-segment-width x y), env(viewport-segment-left x y) usw. decken dasselbe Modell ab.

Ändert sich die Haltung des Geräts (Aufklappen, Drehen, Wechsel in den Split-Modus), ändern sich auch die Segmente. Ein eigenes Ereignis dafür gibt es nicht. Deshalb liest man segments bei resize neu aus oder hört mit matchMedia() auf Änderungen der Segment-Media-Queries.

Parameter

Name Typ Default Beschreibung
$segments DOMRect[] | null Schreibgeschützte Eigenschaft (kein Parameter im eigentlichen Sinn): ein Array von DOMRect-Objekten, eines pro Viewport-Segment, geordnet von links nach rechts bzw. von oben nach unten. In eingebetteten Frames null.

Rückgabewert

Typ
Viewport
Beschreibung
window.viewport liefert das Viewport-Objekt des aktuellen Fensters. viewport.segments liefert DOMRect[] oder null.

Beispiele

Unterstützung prüfen und Segmente ausgeben

// Viewport-Objekt holen (kein Konstruktor, nur über window.viewport)
if ('viewport' in window && window.viewport.segments) {
  const { segments } = window.viewport;
  console.log(`Anzahl Segmente: ${segments.length}`);
  segments.forEach((rect, i) => {
    console.log(`Segment ${i}: x=${rect.x}, y=${rect.y}, ${rect.width}×${rect.height}`);
  });
} else {
  console.log('Viewport Segments API nicht verfügbar');
}
Anzahl Segmente: 2 Segment 0: x=0, y=0, 884×1104 Segment 1: x=928, y=0, 884×1104

Zweispaltiges Layout an der Falz ausrichten

const list = document.querySelector('#liste');
const detail = document.querySelector('#detail');

const applyLayout = () => {
  const segments = window.viewport?.segments;
  if (segments && segments.length === 2 && segments[0].x !== segments[1].x) {
    // Nebeneinander liegende Segmente: Liste links, Details rechts
    const [left, right] = segments;
    Object.assign(list.style, { position: 'fixed', left: `${left.x}px`, width: `${left.width}px` });
    Object.assign(detail.style, { position: 'fixed', left: `${right.x}px`, width: `${right.width}px` });
    document.body.dataset.layout = 'dual';
  } else {
    list.removeAttribute('style');
    detail.removeAttribute('style');
    document.body.dataset.layout = 'single';
  }
};

applyLayout();
// Kein eigenes Ereignis: bei resize neu berechnen
window.addEventListener('resize', applyLayout);

Auf Wechsel der Gerätehaltung per matchMedia reagieren

const dualHorizontal = window.matchMedia('(horizontal-viewport-segments: 2)');

const onChange = (event) => {
  const count = window.viewport?.segments?.length ?? 1;
  console.log(event.matches
    ? `Aufgeklappt, ${count} Segmente nebeneinander`
    : 'Einzelnes Segment');
};

dualHorizontal.addEventListener('change', onChange);
onChange(dualHorizontal); // Anfangszustand auswerten
Aufgeklappt, 2 Segmente nebeneinander

Dialog nicht über das Scharnier legen

const placeDialog = (dialog) => {
  const segments = window.viewport?.segments ?? [];
  // Größtes Segment wählen und den Dialog darin zentrieren
  const target = segments.reduce(
    (best, r) => (r.width * r.height > best.width * best.height ? r : best),
    { x: 0, y: 0, width: innerWidth, height: innerHeight }
  );
  dialog.style.left = `${target.x + target.width / 2}px`;
  dialog.style.top = `${target.y + target.height / 2}px`;
  dialog.style.translate = '-50% -50%';
};

placeDialog(document.querySelector('#hinweis'));

// Wichtig · Fallstricke

  • Experimentell: Die API ist derzeit nur in Chromium-Browsern ab Version 138 verfügbar (Chrome, Edge, auf Android und Desktop). Firefox und Safari unterstützen sie nicht. Prüfen Sie deshalb immer mit 'viewport' in window oder optionaler Verkettung (window.viewport?.segments).
  • Kein Ereignis für Änderungen: segments ist eine Momentaufnahme. Lesen Sie den Wert bei resize neu aus oder nutzen Sie matchMedia() mit horizontal-viewport-segments bzw. vertical-viewport-segments. Gespeicherte DOMRect-Objekte werden nicht automatisch aktualisiert.
  • iframes: In eingebetteten Frames liefert segments null. Nur das oberste Dokument erhält Segmentinformationen.
  • Zwischen zwei Segmenten kann eine Lücke liegen (die Breite des Scharniers). Berechnen Sie diese als segments[1].x - (segments[0].x + segments[0].width) und legen Sie dort keine interaktiven Elemente ab.
  • Für reine Layout-Anpassungen sind die CSS-Media-Features und die Umgebungsvariablen env(viewport-segment-*) oft einfacher und leistungsfähiger als JavaScript. Das Layout reagiert dann ohne Skript und ohne Neuberechnung.
  • Nicht verwechseln mit window.visualViewport (VisualViewport). Dieses Objekt beschreibt Zoom und Bildlaufposition, nicht die physische Teilung des Bildschirms.