Ein Aufrufübergang zwischen zwei verschiedenen Dokumenten wird als dokumentübergreifender Übergang bezeichnet. Dies ist normalerweise bei mehrseitigen Anwendungen (MPA) der Fall. Ab Chrome 126 werden in Chrome dokumentübergreifende Übergänge für die Ansicht unterstützt.
Unterstützte Browser
- <ph type="x-smartling-placeholder">
- <ph type="x-smartling-placeholder">
- <ph type="x-smartling-placeholder">
- <ph type="x-smartling-placeholder">
Dokumentübergreifende Übergänge basieren auf denselben Bausteinen und Prinzipien wie Übergänge bei Ansichten in demselben Dokument. Dies ist sehr bewusst:
- Der Browser erstellt Snapshots von Elementen mit einer eindeutigen
view-transition-name
sowohl auf der alten als auch auf der neuen Seite. - Das DOM wird aktualisiert, während das Rendering unterdrückt wird.
- Und schließlich werden die Übergänge von CSS-Animationen unterstützt.
Der Unterschied zu Ansichtsübergängen für dasselbe Dokument besteht darin, dass Sie bei dokumentübergreifenden Änderungen der Ansicht nicht document.startViewTransition
aufrufen müssen, um einen Ansichtsübergang zu starten. Der Trigger für eine dokumentübergreifende Ansichtsumstellung ist stattdessen eine Navigation am selben Ursprung von einer Seite zur anderen. Diese Aktion wird normalerweise durch den Nutzer Ihrer Website ausgeführt, der auf einen Link klickt.
Mit anderen Worten: Es gibt keine API, die aufgerufen werden kann, um einen Ansichtsübergang zwischen zwei Dokumenten zu starten. Es müssen jedoch zwei Bedingungen erfüllt sein:
- Beide Dokumente müssen denselben Ursprung haben.
- Beide Seiten müssen aktiviert werden, damit ein Wechsel der Ansicht möglich ist.
Beide Bedingungen werden weiter unten in diesem Dokument erläutert.
Dokumentübergreifende Übergänge in der Ansicht sind auf Navigationen am selben Ursprung beschränkt
Dokumentübergreifende Übergänge in der Ansicht sind nur auf Navigationen mit demselben Ursprung beschränkt. Eine Navigation gilt als derselbe Ursprung, wenn der Ursprung beider teilnehmenden Seiten gleich ist.
Der Ursprung einer Seite ist eine Kombination aus verwendetem Schema, Hostname und Port, wie auf web.dev beschrieben.
<ph type="x-smartling-placeholder">So kann es beispielsweise beim Wechsel von developer.chrome.com
nach developer.chrome.com/blog
zu einem dokumentübergreifenden Ansichtswechsel kommen, da diese beiden Quellen denselben Ursprung haben.
Bei der Navigation von developer.chrome.com
nach www.chrome.com
ist dieser Übergang nicht möglich, da diese ursprungsübergreifend und zur selben Website gehören.
Der Wechsel der dokumentübergreifenden Ansicht ist optional.
Damit ein dokumentübergreifender Wechsel zwischen zwei Dokumenten möglich ist, müssen beide teilnehmenden Seiten dies zulassen. Dies erfolgt mit der @view-transition
-at-Regel in CSS.
Legen Sie in der At-Regel @view-transition
den Deskriptor navigation
auf auto
fest, um Ansichtsübergänge für dokumentübergreifende Navigation am selben Ursprung zu ermöglichen.
@view-transition {
navigation: auto;
}
Wenn Sie den navigation
-Deskriptor auf auto
festlegen, werden für die folgenden NavigationType Ansichtenübergänge zugelassen:
traverse
push
oderreplace
, wenn die Aktivierung nicht vom Nutzer über die Benutzeroberfläche des Browsers initiiert wurde.
Von auto
ausgeschlossene Navigationen sind z. B. das Navigieren über die URL-Adressleiste oder das Klicken auf ein Lesezeichen sowie jede Art von Aktualisierung durch Nutzer oder Skripts.
Wenn eine Navigation zu lange dauert – im Fall von Chrome mehr als vier Sekunden – wird der Übergang mit TimeoutError
DOMException
übersprungen.
Demo zum Wechsel der dokumentübergreifenden Ansicht
In der folgenden Demo werden Ansichtsübergänge verwendet, um eine Stack Navigator-Demo zu erstellen. Hier gibt es keine Aufrufe für document.startViewTransition()
. Die Übergänge bei der Ansicht werden durch das Wechseln von einer Seite zu einer anderen ausgelöst.
Übergänge dokumentübergreifender Ansichten anpassen
Zum Anpassen von dokumentübergreifenden Übergängen der Ansicht können Sie einige Webplattformfunktionen verwenden.
- Die Ereignisse
pageswap
undpagereveal
- Informationen zur Aktivierung der Navigation
- Blockierung des Renderings
Diese Funktionen sind nicht Teil der View Transition API-Spezifikation selbst, sondern für die gemeinsame Verwendung mit ihr vorgesehen.
Die Ereignisse pageswap
und pagereveal
Unterstützte Browser
- <ph type="x-smartling-placeholder">
- <ph type="x-smartling-placeholder">
- <ph type="x-smartling-placeholder">
- <ph type="x-smartling-placeholder">
Die HTML-Spezifikation enthält zwei neue Ereignisse, die Sie verwenden können, um dokumentübergreifende Übergänge bei Ansichten anzupassen: pageswap
und pagereveal
.
Diese beiden Ereignisse werden für jede dokumentübergreifende Navigation am selben Ursprung ausgelöst, unabhängig davon, ob ein Aufrufübergang stattfindet oder nicht. Wenn ein Ansichtsübergang zwischen den beiden Seiten bevorsteht, können Sie bei diesen Ereignissen über die Eigenschaft viewTransition
auf das ViewTransition
-Objekt zugreifen.
- Das
pageswap
-Ereignis wird ausgelöst, bevor der letzte Frame einer Seite gerendert wird. Damit können Sie in letzter Minute Änderungen auf der ausgehenden Seite vornehmen, bevor die alten Snapshots erstellt werden. - Das
pagereveal
-Ereignis wird auf einer Seite ausgelöst, nachdem sie initialisiert oder reaktiviert wurde, jedoch vor der ersten Rendering-Empfehlung. Damit können Sie die neue Seite anpassen, bevor die neuen Snapshots erstellt werden.
Sie können diese Ereignisse beispielsweise verwenden, um schnell einige view-transition-name
-Werte festzulegen oder zu ändern oder Daten von einem Dokument in ein anderes zu übertragen. Dazu werden Daten aus sessionStorage
geschrieben und gelesen, um den Ansichtsübergang anzupassen, bevor der Übergang tatsächlich ausgeführt wird.
let lastClickX, lastClickY;
document.addEventListener('click', (event) => {
if (event.target.tagName.toLowerCase() === 'a') return;
lastClickX = event.clientX;
lastClickY = event.clientY;
});
// Write position to storage on old page
window.addEventListener('pageswap', (event) => {
if (event.viewTransition && lastClick) {
sessionStorage.setItem('lastClickX', lastClickX);
sessionStorage.setItem('lastClickY', lastClickY);
}
});
// Read position from storage on new page
window.addEventListener('pagereveal', (event) => {
if (event.viewTransition) {
lastClickX = sessionStorage.getItem('lastClickX');
lastClickY = sessionStorage.getItem('lastClickY');
}
});
Wenn Sie möchten, können Sie den Übergang in beiden Ereignissen überspringen.
window.addEventListener("pagereveal", async (e) => {
if (e.viewTransition) {
if (goodReasonToSkipTheViewTransition()) {
e.viewTransition.skipTransition();
}
}
}
Das ViewTransition
-Objekt in pageswap
und pagereveal
sind zwei verschiedene Objekte. Sie gehen auch unterschiedlich mit den verschiedenen Versprechen um:
pageswap
: Sobald das Dokument ausgeblendet ist, wird das alteViewTransition
-Objekt übersprungen. In diesem Fall lehntviewTransition.ready
den Vorgang ab undviewTransition.finished
wird aufgelöst.pagereveal
: Das Versprechen vonupdateCallBack
ist an diesem Punkt bereits erledigt. Du kannst die PromiseviewTransition.ready
undviewTransition.finished
verwenden.
Informationen zur Aktivierung der Navigation
Unterstützte Browser
- <ph type="x-smartling-placeholder">
- <ph type="x-smartling-placeholder">
- <ph type="x-smartling-placeholder">
- <ph type="x-smartling-placeholder">
Sowohl beim Ereignis pageswap
als auch beim Ereignis pagereveal
können Sie Aktionen basierend auf den URLs der alten und der neuen Seite ausführen.
Beispielsweise hängt die Art der zu verwendenden Animation im MPA Stack Navigator vom Navigationspfad ab:
- Wenn Sie von der Übersichtsseite zur Detailseite wechseln, muss der neue Inhalt von rechts nach links eingeschoben werden.
- Wenn Sie von der Detailseite zur Übersichtsseite wechseln, muss der alte Inhalt von links nach rechts herausfallen.
Dazu benötigst du Informationen über die Navigation, die im Fall von pageswap
bevorsteht bzw. im Fall von pagereveal
gerade erfolgt ist.
Dazu können Browser jetzt NavigationActivation
-Objekte verfügbar machen, die Informationen zur Navigation am selben Ursprung enthalten. Dieses Objekt gibt den verwendeten Navigationstyp, die aktuellen Einträge und die endgültigen Zielverlaufseinträge aus navigation.entries()
der Navigation API an.
Auf einer aktivierten Seite können Sie über navigation.activation
auf dieses Objekt zugreifen. Im pageswap
-Ereignis können Sie über e.activation
darauf zugreifen.
Sehen Sie sich diese Profile-Demo an, in der NavigationActivation
-Informationen in den Ereignissen pageswap
und pagereveal
verwendet werden, um view-transition-name
-Werte für die Elemente festzulegen, die am Aufrufübergang beteiligt sein müssen.
So musst du nicht jeden einzelnen Artikel in der Liste im Voraus mit einem view-transition-name
dekorieren. Stattdessen geschieht dies Just-in-Time mit JavaScript, nur bei Elementen, die es benötigen.
Der Code lautet wie folgt:
// OLD PAGE LOGIC
window.addEventListener('pageswap', async (e) => {
if (e.viewTransition) {
const targetUrl = new URL(e.activation.entry.url);
// Navigating to a profile page
if (isProfilePage(targetUrl)) {
const profile = extractProfileNameFromUrl(targetUrl);
// Set view-transition-name values on the clicked row
document.querySelector(`#${profile} span`).style.viewTransitionName = 'name';
document.querySelector(`#${profile} img`).style.viewTransitionName = 'avatar';
// Remove view-transition-names after snapshots have been taken
// (this to deal with BFCache)
await e.viewTransition.finished;
document.querySelector(`#${profile} span`).style.viewTransitionName = 'none';
document.querySelector(`#${profile} img`).style.viewTransitionName = 'none';
}
}
});
// NEW PAGE LOGIC
window.addEventListener('pagereveal', async (e) => {
if (e.viewTransition) {
const fromURL = new URL(navigation.activation.from.url);
const currentURL = new URL(navigation.activation.entry.url);
// Navigating from a profile page back to the homepage
if (isProfilePage(fromURL) && isHomePage(currentURL)) {
const profile = extractProfileNameFromUrl(currentURL);
// Set view-transition-name values on the elements in the list
document.querySelector(`#${profile} span`).style.viewTransitionName = 'name';
document.querySelector(`#${profile} img`).style.viewTransitionName = 'avatar';
// Remove names after snapshots have been taken
// so that we're ready for the next navigation
await e.viewTransition.ready;
document.querySelector(`#${profile} span`).style.viewTransitionName = 'none';
document.querySelector(`#${profile} img`).style.viewTransitionName = 'none';
}
}
});
Der Code wird auch automatisch bereinigt, indem die view-transition-name
-Werte nach Ausführung des Ansichtsübergangs entfernt werden. Auf diese Weise ist die Seite für aufeinanderfolgende Navigationen bereit und kann auch den Verlauf des Verlaufs durchlaufen.
Verwenden Sie dazu diese Dienstfunktion, die view-transition-name
s vorübergehend festlegt.
const setTemporaryViewTransitionNames = async (entries, vtPromise) => {
for (const [$el, name] of entries) {
$el.style.viewTransitionName = name;
}
await vtPromise;
for (const [$el, name] of entries) {
$el.style.viewTransitionName = '';
}
}
Der vorherige Code kann jetzt so vereinfacht werden:
// OLD PAGE LOGIC
window.addEventListener('pageswap', async (e) => {
if (e.viewTransition) {
const targetUrl = new URL(e.activation.entry.url);
// Navigating to a profile page
if (isProfilePage(targetUrl)) {
const profile = extractProfileNameFromUrl(targetUrl);
// Set view-transition-name values on the clicked row
// Clean up after the page got replaced
setTemporaryViewTransitionNames([
[document.querySelector(`#${profile} span`), 'name'],
[document.querySelector(`#${profile} img`), 'avatar'],
], e.viewTransition.finished);
}
}
});
// NEW PAGE LOGIC
window.addEventListener('pagereveal', async (e) => {
if (e.viewTransition) {
const fromURL = new URL(navigation.activation.from.url);
const currentURL = new URL(navigation.activation.entry.url);
// Navigating from a profile page back to the homepage
if (isProfilePage(fromURL) && isHomePage(currentURL)) {
const profile = extractProfileNameFromUrl(currentURL);
// Set view-transition-name values on the elements in the list
// Clean up after the snapshots have been taken
setTemporaryViewTransitionNames([
[document.querySelector(`#${profile} span`), 'name'],
[document.querySelector(`#${profile} img`), 'avatar'],
], e.viewTransition.ready);
}
}
});
Mit Blockierung des Renderings warten, bis Inhalte geladen werden
Unterstützte Browser
- <ph type="x-smartling-placeholder">
- <ph type="x-smartling-placeholder">
- <ph type="x-smartling-placeholder">
- <ph type="x-smartling-placeholder">
In einigen Fällen kann es sinnvoll sein, das erste Rendern einer Seite zu warten, bis ein bestimmtes Element im neuen DOM vorhanden ist. So wird Blinken vermieden und der Status der Animation muss stabil sein.
Definiere im <head>
eine oder mehrere Element-IDs, die vorhanden sein müssen, bevor die Seite zum ersten Mal gerendert wird. Verwende dazu das folgende Meta-Tag.
<link rel="expect" blocking="render" href="#section1">
Dieses Meta-Tag bedeutet, dass das Element im DOM vorhanden sein sollte, nicht, dass der Inhalt geladen werden soll. Bei Bildern reicht beispielsweise das bloße Vorhandensein des <img>
-Tags mit dem angegebenen id
im DOM-Baum aus, damit die Bedingung als „true“ ausgewertet wird. Möglicherweise wird das Bild noch geladen.
Bevor Sie sich für eine Komplettblockierung entscheiden, sollten Sie sich bewusst sein, dass das inkrementelle Rendering ein grundlegender Aspekt des Webs ist. Seien Sie also vorsichtig, wenn Sie das Rendering blockieren. Welche Auswirkungen das Blockieren des Renderings hat, muss von Fall zu Fall bewertet werden. Standardmäßig sollten Sie blocking=render
nur dann verwenden, wenn Sie die Auswirkungen auf Ihre Nutzer aktiv messen und messen können, indem Sie die Auswirkungen auf Ihre Core Web Vitals messen.
Übergangstypen bei dokumentübergreifenden Übergängen der Ansicht ansehen
Bei dokumentübergreifenden Ansichtsübergängen werden auch Arten von Ansichten unterstützt, mit denen die Animationen und die erfassten Elemente angepasst werden können.
Wenn Sie beispielsweise bei einer Paginierung zur nächsten oder vorherigen Seite wechseln, können Sie verschiedene Animationen verwenden, je nachdem, ob Sie zu einer höheren oder einer niedrigeren Seite aus der Abfolge springen.
Wenn Sie diese Typen im Voraus festlegen möchten, fügen Sie die Typen in der At-Regel @view-transition
hinzu:
@view-transition {
navigation: auto;
types: slide, forwards;
}
Wenn Sie die Typen spontan festlegen möchten, verwenden Sie die Ereignisse pageswap
und pagereveal
, um den Wert von e.viewTransition.types
zu ändern.
window.addEventListener("pagereveal", async (e) => {
if (e.viewTransition) {
const transitionType = determineTransitionType(navigation.activation.from, navigation.activation.entry);
e.viewTransition.types.add(transitionType);
}
});
Die Typen werden nicht automatisch vom ViewTransition
-Objekt der alten Seite in das ViewTransition
-Objekt der neuen Seite übernommen. Sie müssen mindestens auf der neuen Seite den Typ bzw. die Typen bestimmen, die verwendet werden sollen, damit die Animationen erwartungsgemäß ausgeführt werden.
Um auf diese Typen zu reagieren, verwenden Sie den Pseudoklassenselektor :active-view-transition-type()
auf dieselbe Weise wie bei Übergängen bei der Ansicht für das gleiche Dokument.
/* Determine what gets captured when the type is forwards or backwards */
html:active-view-transition-type(forwards, backwards) {
:root {
view-transition-name: none;
}
article {
view-transition-name: content;
}
.pagination {
view-transition-name: pagination;
}
}
/* Animation styles for forwards type only */
html:active-view-transition-type(forwards) {
&::view-transition-old(content) {
animation-name: slide-out-to-left;
}
&::view-transition-new(content) {
animation-name: slide-in-from-right;
}
}
/* Animation styles for backwards type only */
html:active-view-transition-type(backwards) {
&::view-transition-old(content) {
animation-name: slide-out-to-right;
}
&::view-transition-new(content) {
animation-name: slide-in-from-left;
}
}
/* Animation styles for reload type only */
html:active-view-transition-type(reload) {
&::view-transition-old(root) {
animation-name: fade-out, scale-down;
}
&::view-transition-new(root) {
animation-delay: 0.25s;
animation-name: fade-in, scale-up;
}
}
Da Typen nur für einen Active View-Übergang gelten, werden Typen automatisch bereinigt, wenn ein Ansichtsübergang abgeschlossen ist. Daher funktionieren Typen gut mit Funktionen wie BFCache.
Demo
In der folgenden Demo zur Paginierung wird der Seiteninhalt je nach Seitennummer, die Sie aufrufen, vor- oder zurückgeschoben.
<ph type="x-smartling-placeholder">Der zu verwendende Übergangstyp wird in den Ereignissen pagereveal
und pageswap
anhand der URLs zu und von dieser festgelegt.
const determineTransitionType = (fromNavigationEntry, toNavigationEntry) => {
const currentURL = new URL(fromNavigationEntry.url);
const destinationURL = new URL(toNavigationEntry.url);
const currentPathname = currentURL.pathname;
const destinationPathname = destinationURL.pathname;
if (currentPathname === destinationPathname) {
return "reload";
} else {
const currentPageIndex = extractPageIndexFromPath(currentPathname);
const destinationPageIndex = extractPageIndexFromPath(destinationPathname);
if (currentPageIndex > destinationPageIndex) {
return 'backwards';
}
if (currentPageIndex < destinationPageIndex) {
return 'forwards';
}
return 'unknown';
}
};
Feedback
Wir freuen uns immer über Feedback von Entwicklern. Wenn Sie etwas teilen möchten, melden Sie ein Problem bei der CSS Working Group auf GitHub und geben Sie dabei Vorschläge und Fragen. Stellen Sie dem Problem [css-view-transitions]
voran.
Sollten Sie auf einen Fehler stoßen, melden Sie den Fehler in Chromium.