Signatur
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
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');
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;
}
*/
// 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 pertypeof 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
finishedder alten Transition wird trotzdem erfüllt,readykann dagegen abgelehnt werden. Abgelehnte Promises sollte man abfangen. - Eindeutige Namen: Kommt ein
view-transition-nameim selben Teilbaum doppelt vor, wird die Transition übersprungen undreadyabgelehnt. - 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: layoutzu geben. - Fehler im Callback: Wirft der Aktualisierungs-Callback einen Fehler oder wird sein Promise abgelehnt, wird die Transition übersprungen.
updateCallbackDoneundfinishedwerden dann ebenfalls abgelehnt. - Barrierefreiheit: Mit
@media (prefers-reduced-motion: reduce)sollte man die Animationen abschwächen oder abschalten.