Overgangen tussen documenten bekijken voor toepassingen met meerdere pagina's

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.

Browser Support

  • Chrome: 126.
  • Rand: 126.
  • Firefox: niet ondersteund.
  • Safari: 18.2.

Source

Overgangen tussen verschillende documentweergaven zijn gebaseerd op dezelfde bouwstenen en principes als overgangen binnen hetzelfde document , en dat is zeer bewust zo gedaan:

  1. De browser maakt momentopnamen van elementen met een unieke view-transition-name op zowel de oude als de nieuwe pagina.
  2. De DOM wordt bijgewerkt terwijl de weergave is onderdrukt.
  3. 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 .

Een voorbeeld-URL met het schema, de hostnaam en de poort gemarkeerd. Samen vormen ze de oorsprong.
Een voorbeeld-URL met het schema, de hostnaam en de poort gemarkeerd. Samen vormen ze de oorsprong.

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
  • push of replace als 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.

Opname van de Stack Navigator-demo . Vereist Chrome 126 of hoger.

Pas overgangen tussen documentweergaven aan.

Om de overgangen tussen documentweergaven aan te passen, kunt u gebruikmaken van een aantal functies van het webplatform.

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

Browser Support

  • Chrome: 124.
  • Rand: 124.
  • Firefox: niet ondersteund.
  • Safari: 18.2.

Source

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 pageswap gebeurtenis 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 pagereveal gebeurtenis 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 oude ViewTransition object overgeslagen. Wanneer dat gebeurt, wordt viewTransition.ready afgewezen en viewTransition.finished afgehandeld.
  • pagereveal : De updateCallBack promise is op dit punt al opgelost. Je kunt de viewTransition.ready en viewTransition.finished -promises gebruiken.

Browser Support

  • Chrome: 123.
  • Rand: 123.
  • Firefox: 147.
  • Safari: 26.2.

Source

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.

Opname van de Profiles-demo . Vereist Chrome 126 of hoger.

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

  • Chrome: 124.
  • Rand: 124.
  • Firefox: niet ondersteund.
  • Safari: niet ondersteund.

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.

Opname van de pagineringsdemo (MPA) . Deze demo maakt gebruik van verschillende overgangen, afhankelijk van de pagina waarnaar je gaat.

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 .