Start · Sprachen · JavaScript · Referenz · ViewTransition

ViewTransition

Schnittstelle

Stellt eine laufende Ansichtstransition der View Transition API dar und bietet Promises für ihre Phasen sowie Methoden zum Überspringen und für Transitionstypen.

seit JavaScript Chrome/Edge 111+, Safari 18+, Firefox 144+ (dokume Kategorie: webapi

Signatur

interface ViewTransition

Beschreibung

Ein ViewTransition-Objekt stellt eine aktive Ansichtstransition dar. Innerhalb eines Dokuments (Same-Document) erhältst du es als Rückgabewert von document.startViewTransition(). Bei dokumentübergreifenden Transitionen (Cross-Document) steht es in den Events pageswap (event.viewTransition) und pagereveal zur Verfügung. Mit dem Objekt kannst du die Phasen der Transition verfolgen, eigene Animationen per Web Animations API einhängen oder die Transition abbrechen.

Das Interface hat folgende Bestandteile:

  • updateCallbackDone: Promise<void>. Wird erfüllt, sobald das Promise des Update-Callbacks erfüllt ist, also wenn das DOM aktualisiert wurde. Wird abgelehnt, wenn der Callback fehlschlägt.
  • ready: Promise<void>. Wird erfüllt, sobald der Pseudo-Element-Baum (::view-transition …) erzeugt ist und die Animation gleich beginnt. Das ist der richtige Zeitpunkt für eigene Animationen mit element.animate().
  • finished: Promise<void>. Wird erfüllt, wenn die Animation beendet ist und die neue Ansicht voll sichtbar und bedienbar ist. Es wird nicht abgelehnt, wenn nur die Animation übersprungen wird. Abgelehnt wird es nur, wenn der Update-Callback fehlschlägt.
  • types: ein ViewTransitionTypeSet (Set-ähnlich). Damit lassen sich Transitionstypen zur Laufzeit setzen, die in CSS per :active-view-transition-type() abgefragt werden.
  • skipTransition(): überspringt den Animationsteil. Der Update-Callback wird trotzdem ausgeführt.

Die Promises passen zu drei typischen Aufgaben: Mit updateCallbackDone reagierst du auf den neuen DOM-Zustand, egal ob animiert wird oder nicht. Mit ready startest du eigene Animationen. Mit finished räumst du auf, etwa Klassen entfernen oder den Fokus setzen.

Rückgabewert

Typ
ViewTransition
Beschreibung
Du erzeugst die Instanz nicht selbst, es gibt keinen öffentlichen Konstruktor. Sie kommt von document.startViewTransition() bzw. aus PageSwapEvent.viewTransition / PageRevealEvent.viewTransition.

Beispiele

Transition starten und Phasen verfolgen

const updateList = async () => {
  const items = await fetch('/api/items').then((r) => r.json());
  document.querySelector('#list').innerHTML = items
    .map((i) => `<li>${i.name}</li>`)
    .join('');
};

const refresh = async () => {
  // Ausweichlösung für Browser ohne Unterstützung
  if (!document.startViewTransition) {
    await updateList();
    return;
  }

  const transition = document.startViewTransition(updateList);

  await transition.updateCallbackDone;
  console.log('DOM aktualisiert');

  await transition.ready;
  console.log('Animation startet');

  await transition.finished;
  console.log('Transition abgeschlossen');
};

refresh();
DOM aktualisiert Animation startet Transition abgeschlossen

Eigene Kreis-Animation im ready-Promise

const toggleTheme = async (event) => {
  const x = event.clientX;
  const y = event.clientY;
  const radius = Math.hypot(
    Math.max(x, innerWidth - x),
    Math.max(y, innerHeight - y)
  );

  const transition = document.startViewTransition(() => {
    document.documentElement.classList.toggle('dark');
  });

  await transition.ready;

  // Pseudo-Element der neuen Ansicht animieren
  document.documentElement.animate(
    {
      clipPath: [
        `circle(0px at ${x}px ${y}px)`,
        `circle(${radius}px at ${x}px ${y}px)`
      ]
    },
    {
      duration: 500,
      easing: 'ease-in-out',
      pseudoElement: '::view-transition-new(root)'
    }
  );
};

document.querySelector('#theme-btn').addEventListener('click', toggleTheme);

Transition bei reduzierter Bewegung überspringen

const prefersReduced = matchMedia('(prefers-reduced-motion: reduce)').matches;

const transition = document.startViewTransition(() => {
  document.querySelector('#panel').hidden = false;
});

if (prefersReduced) {
  // DOM-Update läuft trotzdem, nur die Animation entfällt
  transition.skipTransition();
}

transition.finished.then(() => {
  document.querySelector('#panel').focus();
  console.log('Panel sichtbar');
});
Panel sichtbar

Transitionstypen für Vor/Zurück-Navigation

const navigate = (direction, render) => {
  const transition = document.startViewTransition({
    update: render,
    types: [direction] // 'forwards' oder 'backwards'
  });
  return transition.finished;
};

// Typ auch nachträglich über das types-Set änderbar
window.addEventListener('pagereveal', (event) => {
  if (event.viewTransition) {
    event.viewTransition.types.add('reveal');
    console.log([...event.viewTransition.types]);
  }
});

/* CSS:
html:active-view-transition-type(backwards) {
  view-transition-name: none;
}
*/
["reveal"]

// Wichtig · Fallstricke

  • Unterstützung prüfen: Frag vor der Nutzung document.startViewTransition ab. Chromium unterstützt die API seit Version 111, Safari seit 18, Firefox erst in neueren Versionen (ab 144). Dokumentübergreifende Transitionen per @view-transition { navigation: auto; } gibt es nur in Chromium 126+ und Safari 18.2+. Transitionstypen werden nicht überall gleich unterstützt.
  • Unbehandelte Ablehnungen: Wird skipTransition() aufgerufen oder schlägt die Transition fehl (etwa wegen doppelter view-transition-name-Werte), wird ready abgelehnt. Ohne .catch() erscheint dann ein „Uncaught (in promise)“-Fehler in der Konsole.
  • Nur eine Transition gleichzeitig: Ein neuer Aufruf von startViewTransition() überspringt die laufende Transition. Deren ready wird mit einem AbortError abgelehnt.
  • Timeout: Braucht der Update-Callback zu lange (in Chromium etwa 4 Sekunden), bricht der Browser mit einem TimeoutError ab. Während der Transition wird die Seite nicht gerendert, daher sollten lange Netzwerkanfragen vor dem Aufruf erledigt werden.
  • Eindeutige Namen: Jeder view-transition-name darf pro Zustand nur einmal vorkommen, sonst wird die Transition übersprungen.
  • Barrierefreiheit: Berücksichtige prefers-reduced-motion in CSS oder rufe skipTransition() auf.
  • Sicherheit: Wenn im Update-Callback per innerHTML eingefügt wird, müssen Daten escaped werden, sonst droht XSS. Das hat mit der API selbst nichts zu tun.