Wanneer er een overgang plaatsvindt tussen twee verschillende documenten, spreken we van een overgang tussen verschillende documentweergaven . Dit is typisch het geval bij applicaties met meerdere pagina's (MPA's). Overgangen tussen verschillende documentweergaven worden in Chrome ondersteund vanaf versie 126.
Overgangen tussen verschillende documentweergaven zijn gebaseerd op dezelfde bouwstenen en principes als overgangen binnen hetzelfde document , en dat is zeer bewust zo gedaan:
- De browser maakt momentopnamen van elementen met een unieke
view-transition-nameop zowel de oude als de nieuwe pagina. - De DOM wordt bijgewerkt terwijl de weergave is onderdrukt.
- En tot slot worden de overgangen mogelijk gemaakt door CSS-animaties.
Het verschil met overgangen tussen pagina's binnen hetzelfde document is dat je bij overgangen tussen pagina's niet document.startViewTransition hoeft aan te roepen om een overgang te starten. De trigger voor een overgang tussen pagina's is in plaats daarvan een navigatie vanaf dezelfde oorsprong van de ene pagina naar de andere, een actie die doorgaans wordt uitgevoerd wanneer de gebruiker van je website op een link klikt.
Met andere woorden, er is geen API die je kunt aanroepen om een weergaveovergang tussen twee documenten te starten. Er zijn echter twee voorwaarden waaraan moet worden voldaan:
- Beide documenten moeten van dezelfde oorsprong zijn.
- Beide pagina's moeten zich aanmelden om de weergaveovergang mogelijk te maken.
Beide voorwaarden worden later in dit document nader toegelicht.
Overgangen tussen documentweergaven zijn beperkt tot navigatie vanaf dezelfde oorsprong.
Overgangen tussen documentweergaven zijn beperkt tot navigaties met dezelfde oorsprong . Een navigatie wordt beschouwd als een navigatie met dezelfde oorsprong als de oorsprong van beide deelnemende pagina's hetzelfde is.
De oorsprong van een pagina is een combinatie van het gebruikte schema, de hostnaam en de poort, zoals gedetailleerd beschreven op web.dev .

Je kunt bijvoorbeeld een overgang tussen documenten hebben wanneer je navigeert van developer.chrome.com naar developer.chrome.com/blog , omdat dit websites van dezelfde oorsprong zijn. Die overgang is niet mogelijk wanneer je navigeert van developer.chrome.com naar www.chrome.com , omdat dit websites van verschillende oorsprong zijn, maar wel van dezelfde site.
Overgangen tussen documentweergaven zijn optioneel.
Om een overgang tussen twee documentweergaven mogelijk te maken, moeten beide pagina's die aan dit proces deelnemen, dit toestaan. Dit wordt gedaan met de @view-transition at-rule in CSS.
Stel in de @view-transition at-rule de navigation in op auto om weergaveovergangen mogelijk te maken voor navigaties tussen documenten met dezelfde oorsprong.
@view-transition {
navigation: auto;
}
Door navigation op auto in te stellen, stemt u ermee in dat weergaveovergangen mogen plaatsvinden voor de volgende NavigationTypes :
-
traverse -
pushofreplaceals de activering niet door de gebruiker via de gebruikersinterface van de browser is geïnitieerd.
Navigaties die niet auto worden verwerkt, zijn bijvoorbeeld navigeren via de adresbalk of klikken op een bladwijzer, evenals elke vorm van door de gebruiker of een script geïnitieerde herlaadactie.
Als een navigatie te lang duurt – in het geval van Chrome langer dan vier seconden – wordt de overgang tussen de weergaven overgeslagen met een TimeoutError DOMException .
Demonstratie van overgangen tussen documentweergaven
Bekijk de volgende demo die gebruikmaakt van weergaveovergangen om een Stack Navigator-demo te maken. Er worden hier geen aanroepen naar document.startViewTransition() gedaan; de weergaveovergangen worden geactiveerd door van de ene pagina naar de andere te navigeren.
Pas overgangen tussen documentweergaven aan.
Om de overgangen tussen documentweergaven aan te passen, kunt u gebruikmaken van een aantal functies van het webplatform.
- De
pageswapenpagerevealonthullingsevenementen - Informatie over het activeren van de navigatie
- Renderblokkering
Deze functies maken geen deel uit van de View Transition API-specificatie zelf, maar zijn ontworpen om in combinatie daarmee te worden gebruikt.
De pageswap en pagereveal onthullingsevenementen
Om je in staat te stellen overgangen tussen documentweergaven aan te passen, bevat de HTML-specificatie twee nieuwe gebeurtenissen die je kunt gebruiken: pageswap en pagereveal .
Deze twee gebeurtenissen worden geactiveerd bij elke navigatie tussen documenten van dezelfde oorsprong, ongeacht of er een overgang tussen weergaven op het punt staat plaats te vinden of niet. Als er een overgang tussen weergaven op het punt staat plaats te vinden tussen de twee pagina's, kunt u het ViewTransition object benaderen via de viewTransition eigenschap van deze gebeurtenissen.
- De
pageswapgebeurtenis wordt geactiveerd voordat het laatste frame van een pagina wordt weergegeven. Je kunt dit gebruiken om nog snel wat wijzigingen aan te brengen op de pagina die wordt uitgewisseld, vlak voordat de oude momentopnamen worden gemaakt. - De
pagerevealgebeurtenis wordt geactiveerd op een pagina nadat deze is geïnitialiseerd of opnieuw geactiveerd, maar vóór de eerste weergavemogelijkheid. Hiermee kunt u de nieuwe pagina aanpassen voordat de nieuwe momentopnamen worden gemaakt.
Je kunt deze gebeurtenissen bijvoorbeeld gebruiken om snel bepaalde waarden view-transition-name in te stellen of te wijzigen, of om gegevens van het ene document naar het andere door te geven door gegevens uit sessionStorage te schrijven en te lezen, zodat je de weergaveovergang kunt aanpassen voordat deze daadwerkelijk wordt uitgevoerd.
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');
}
});
Als je wilt, kun je ervoor kiezen om de overgang bij beide evenementen over te slaan.
window.addEventListener("pagereveal", async (e) => {
if (e.viewTransition) {
if (goodReasonToSkipTheViewTransition()) {
e.viewTransition.skipTransition();
}
}
}
Het ViewTransition object in pageswap en pagereveal zijn twee verschillende objecten. Ze behandelen de verschillende promises ook op een andere manier:
-
pageswap: Zodra het document verborgen is, wordt het oudeViewTransitionobject overgeslagen. Wanneer dat gebeurt, wordtviewTransition.readyafgewezen enviewTransition.finishedafgehandeld. -
pagereveal: DeupdateCallBackpromise is op dit punt al opgelost. Je kunt deviewTransition.readyenviewTransition.finished-promises gebruiken.
Informatie over het activeren van de navigatie
Bij zowel pageswap als pagereveal events kunt u ook acties ondernemen op basis van de URL's van de oude en nieuwe pagina's.
In de MPA Stack Navigator is het type animatie dat gebruikt moet worden bijvoorbeeld afhankelijk van het navigatiepad:
- Bij het navigeren van de overzichtspagina naar een detailpagina moet de nieuwe inhoud van rechts naar links naar binnen schuiven.
- Bij het navigeren van de detailpagina naar de overzichtspagina moet de oude inhoud van links naar rechts verschuiven.
Hiervoor heb je informatie nodig over de navigatie die, in het geval van pageswap , op het punt staat plaats te vinden of, in het geval van pagereveal net heeft plaatsgevonden.
Browsers kunnen nu NavigationActivation objecten beschikbaar stellen die informatie bevatten over de navigatie vanaf dezelfde oorsprong. Dit object toont het gebruikte navigatietype, de huidige en de uiteindelijke bestemming in de navigatiegeschiedenis, zoals te vinden in navigation.entries() van de Navigation API .
Op een geactiveerde pagina heb je toegang tot dit object via navigation.activation . In de pageswap gebeurtenis heb je toegang tot dit object via e.activation .
Bekijk deze Profiles-demo die NavigationActivation informatie gebruikt in de pageswap en pagereveal -events om de view-transition-name waarden in te stellen voor de elementen die aan de weergaveovergang moeten deelnemen.
Op die manier hoef je niet elk item in de lijst vooraf te voorzien van een view-transition-name . In plaats daarvan gebeurt dit pas op het juiste moment met JavaScript, alleen op de elementen die het nodig hebben.
De code is als volgt:
// 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';
}
}
});
De code ruimt zichzelf ook op door de waarden van view-transition-name te verwijderen nadat de overgang tussen weergaven is uitgevoerd. Op deze manier is de pagina klaar voor volgende navigaties en kan deze ook de navigatiegeschiedenis verwerken.
Gebruik hiervoor de hulpprogrammafunctie die tijdelijk view-transition-name instelt.
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 = '';
}
}
De voorgaande code kan nu als volgt worden vereenvoudigd:
// 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);
}
}
});
Wacht tot de inhoud geladen is met render blocking.
Browser Support
In sommige gevallen is het wellicht verstandig om de eerste weergave van een pagina uit te stellen totdat een bepaald element in de nieuwe DOM aanwezig is. Dit voorkomt flikkeren en zorgt ervoor dat de animatie stabiel blijft.
Definieer in de <head> een of meer element-ID's die aanwezig moeten zijn voordat de pagina voor de eerste keer wordt weergegeven, met behulp van de volgende meta-tag.
<link rel="expect" blocking="render" href="#section1">
Deze meta-tag betekent dat het element in de DOM aanwezig moet zijn, niet dat de inhoud geladen moet zijn. Bijvoorbeeld bij afbeeldingen is de aanwezigheid van de <img> -tag met de opgegeven id in de DOM-structuur voldoende om de voorwaarde te laten kloppen. De afbeelding zelf kan nog steeds aan het laden zijn.
Voordat je volledig overstapt op render blocking, houd er rekening mee dat incrementele rendering een fundamenteel aspect van het web is. Wees daarom voorzichtig bij het kiezen voor blocking rendering. De impact van blocking rendering moet per geval worden beoordeeld. Vermijd standaard het gebruik van blocking=render tenzij je de impact ervan op je gebruikers actief kunt meten en kwantificeren door de impact op je Core Web Vitals te meten.
Weergaveovergangstypen in weergaveovergangen tussen documenten
Overgangen tussen documentweergaven ondersteunen ook verschillende weergavetypen , waarmee de animaties en de elementen die worden vastgelegd, kunnen worden aangepast.
Als je bijvoorbeeld naar de volgende of vorige pagina in een paginering gaat, wil je misschien verschillende animaties gebruiken, afhankelijk van of je naar een hogere of lagere pagina in de reeks gaat.
Om deze typen vooraf in te stellen, voegt u de typen toe aan de @view-transition at-rule:
@view-transition {
navigation: auto;
types: slide, forwards;
}
Om de gegevenstypen dynamisch in te stellen, kunt u de gebeurtenissen pageswap en pagereveal gebruiken om de waarde van e.viewTransition.types te manipuleren.
window.addEventListener("pagereveal", async (e) => {
if (e.viewTransition) {
const transitionType = determineTransitionType(navigation.activation.from, navigation.activation.entry);
e.viewTransition.types.add(transitionType);
}
});
De gegevenstypen worden niet automatisch overgenomen van het ViewTransition object op de oude pagina naar het ViewTransition object op de nieuwe pagina. U moet de te gebruiken gegevenstypen, in ieder geval op de nieuwe pagina, zelf bepalen om ervoor te zorgen dat de animaties naar behoren werken.
Om op deze typen te reageren, gebruikt u de pseudo-klasseselector :active-view-transition-type() op dezelfde manier als bij weergaveovergangen binnen hetzelfde document.
/* 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;
}
}
Omdat typen alleen van toepassing zijn op een actieve weergaveovergang, worden ze automatisch opgeruimd wanneer een weergaveovergang is voltooid. Daardoor werken typen goed samen met functies zoals BFCache .
Demo
In de volgende demonstratie van paginering schuift de pagina-inhoud naar voren of naar achteren, afhankelijk van het paginanummer waarnaar u navigeert.
Het te gebruiken overgangstype wordt bepaald in de pagereveal en pageswap gebeurtenissen door naar de begin- en eind-URL's te kijken.
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
Feedback van ontwikkelaars is altijd welkom. Om feedback te delen, kunt u een issue aanmaken bij de CSS Working Group op GitHub met suggesties en vragen. Voeg [css-view-transitions] toe aan uw issue. Mocht u een bug tegenkomen, meld deze dan bij Chromium .