Start · Sprachen · JavaScript · Referenz · Element.startViewTransition()

Element.startViewTransition()

Methode

Startet eine elementbezogene („scoped“) Ansichtstransition innerhalb desselben Dokuments und gibt ein <code>ViewTransition</code>-Objekt zurück, über das man sie steuert.

seit JavaScript Experimentell: bisher nur Chromium-basierte Browse Kategorie: webapi

Signatur

Element.prototype.startViewTransition(callbackOptions)

Beschreibung

Element.startViewTransition() funktioniert wie document.startViewTransition(), bezieht sich aber nur auf einen Teilbaum des DOM. Das Element, auf dem die Methode aufgerufen wird, ist die Wurzel der Transition. Der Browser erfasst den alten Zustand innerhalb dieses Elements, führt den Aktualisierungs-Callback aus, erfasst den neuen Zustand und animiert zwischen beiden. Der Baum der Pseudo-Elemente (::view-transition, ::view-transition-group(), ::view-transition-old(), ::view-transition-new()) hängt dabei am Wurzel-Element statt am Dokument.

Der größte Vorteil gegenüber der dokumentweiten Variante: Der Rest der Seite bleibt interaktiv und wird nicht „eingefroren“. Außerdem können mehrere Transitionen gleichzeitig auf verschiedenen Elementen laufen, z. B. in einer Liste und in einer Seitenleiste. Solange eine dokumentweite Transition läuft, gilt das nicht, denn dann ist nur eine einzige Transition möglich. Die Transition wird außerdem vom Wurzel-Element beschnitten und liegt in dessen Stapelkontext. Deshalb überlagert sie keine Elemente außerhalb.

Typische Anwendungsfälle sind Komponenten in Single-Page-Anwendungen: Tabs, Karussells, sortierbare Listen, Akkordeons oder Widgets, die ihren Inhalt austauschen, ohne die ganze Seite zu betreffen. Die Elemente, die animiert werden sollen, bekommen wie gewohnt per CSS einen view-transition-name. Die Namen müssen nur innerhalb des jeweiligen Teilbaums eindeutig sein.

Der Aktualisierungs-Callback darf ein Promise zurückgeben. Die Transition wartet dann, bis das Promise erfüllt ist, bevor sie den neuen Zustand erfasst. Mit der Objekt-Form des Arguments lassen sich zusätzlich types angeben. Damit kann man im CSS über :active-view-transition-type() je nach Art der Transition unterschiedliche Animationen auswählen.

Parameter

Name Typ Default Beschreibung
$callbackOptions Function | { update?: Function, types?: string[] } undefined Entweder direkt der Aktualisierungs-Callback, der das DOM im Teilbaum ändert (darf ein Promise zurückgeben), oder ein Objekt mit update (derselbe Callback) und types (Array von Typnamen, die für :active-view-transition-type() im CSS gelten). Fehlt der Callback, wird nur der aktuelle Zustand erfasst und animiert.

Rückgabewert

Typ
ViewTransition
Beschreibung
Ein ViewTransition-Objekt mit den Promises updateCallbackDone, ready und finished, der Methode skipTransition(), der Eigenschaft types und (bei elementbezogenen Transitionen) dem Verweis transitionRoot auf das Wurzel-Element.

Beispiele

Tab-Inhalt mit Fallback animiert austauschen

const panel = document.querySelector('#tab-panel');

const showTab = (html) => {
  const update = () => { panel.innerHTML = html; };

  // Fallback für Browser ohne elementbezogene View Transitions
  if (typeof panel.startViewTransition !== 'function') {
    update();
    return;
  }

  panel.startViewTransition(update);
};

document.querySelectorAll('[data-tab]').forEach((btn) => {
  btn.addEventListener('click', () => {
    showTab(`<p>Inhalt von Tab ${btn.dataset.tab}</p>`);
  });
});

Asynchrones Update mit Promises der Transition

const list = document.querySelector('#produktliste');

const ladeUndZeige = async (kategorie) => {
  const transition = list.startViewTransition(async () => {
    const res = await fetch(`/api/produkte?kat=${encodeURIComponent(kategorie)}`);
    const produkte = await res.json();
    list.replaceChildren(...produkte.map((p) => {
      const li = document.createElement('li');
      li.textContent = p.name;
      li.style.viewTransitionName = `produkt-${p.id}`;
      return li;
    }));
  });

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

ladeUndZeige('buecher');
Animation startet Transition abgeschlossen

Zwei parallele Transitionen mit Typen

const sidebar = document.querySelector('aside');
const main = document.querySelector('main');

// Beide laufen gleichzeitig, weil sie auf verschiedene Teilbäume begrenzt sind
sidebar.startViewTransition({
  update: () => sidebar.classList.toggle('eingeklappt'),
  types: ['einklappen']
});

const t = main.startViewTransition({
  update: () => main.querySelector('.karte')?.remove(),
  types: ['entfernen']
});

console.log([...t.types]);

/* Passendes CSS:
main:active-view-transition-type(entfernen)::view-transition-old(*) {
  animation: 200ms ease-out both ausblenden;
}
*/
["entfernen"]

// Wichtig · Fallstricke

  • Kompatibilität: Elementbezogene View Transitions sind neu und bisher nur in Chromium-basierten Browsern verfügbar. Firefox und Safari unterstützen derzeit nur document.startViewTransition() bzw. noch gar keine View Transitions. Deshalb immer per typeof el.startViewTransition === 'function' prüfen und die DOM-Änderung notfalls ohne Animation ausführen.
  • Nur eine Transition pro Element: Startet man auf demselben Element eine neue Transition, wird die laufende übersprungen. Das Promise finished der alten Transition wird trotzdem erfüllt, ready kann dagegen abgelehnt werden. Abgelehnte Promises sollte man abfangen.
  • Eindeutige Namen: Kommt ein view-transition-name im selben Teilbaum doppelt vor, wird die Transition übersprungen und ready abgelehnt.
  • Layout und Beschneidung: Die Animation wird auf das Wurzel-Element beschnitten. Elemente, die sich aus dem Container hinausbewegen sollen, werden also abgeschnitten. Für stabiles Verhalten empfiehlt die Spezifikation dem Wurzel-Element eine Eingrenzung wie contain: layout zu geben.
  • Fehler im Callback: Wirft der Aktualisierungs-Callback einen Fehler oder wird sein Promise abgelehnt, wird die Transition übersprungen. updateCallbackDone und finished werden dann ebenfalls abgelehnt.
  • Barrierefreiheit: Mit @media (prefers-reduced-motion: reduce) sollte man die Animationen abschwächen oder abschalten.