Overgangen tussen documenten bekijken voor toepassingen met meerdere pagina's

Wanneer er een weergaveovergang plaatsvindt tussen twee verschillende documenten, wordt dit een weergaveovergang tussen verschillende documenten genoemd. Dit is doorgaans het geval bij toepassingen met meerdere pagina's (MPA). Overgangen tussen documentweergaven worden ondersteund in Chrome vanaf Chrome 126.

Browserondersteuning

  • 126
  • 126
  • X
  • X

Bron

Overgangen tussen weergaven tussen documenten zijn gebaseerd op precies dezelfde bouwstenen en principes als overgangen tussen weergaven binnen dezelfde documenten , wat zeer opzettelijk is:

  1. De browser maakt momentopnamen van elementen die een unieke view-transition-name hebben op zowel de oude als de nieuwe pagina.
  2. De DOM wordt bijgewerkt terwijl weergave wordt onderdrukt.
  3. En ten slotte worden de overgangen mogelijk gemaakt door CSS-animaties.

Wat anders is in vergelijking met weergaveovergangen van hetzelfde document, is dat u bij weergaveovergangen tussen verschillende documenten document.startViewTransition niet hoeft aan te roepen om een ​​weergaveovergang te starten. In plaats daarvan is de trigger voor een overgang tussen documentweergaven een navigatie van dezelfde oorsprong van de ene pagina naar de andere, een actie die doorgaans wordt uitgevoerd doordat de gebruiker van uw website op een link klikt.

Met andere woorden: er is geen API die kan worden aangeroepen om een ​​weergaveovergang tussen twee documenten te starten. Er zijn echter twee voorwaarden waaraan moet worden voldaan:

  • Beide documenten moeten op dezelfde oorsprong bestaan.
  • Beide pagina's moeten zich aanmelden om de weergaveovergang mogelijk te maken.

Beide voorwaarden worden verderop in dit document uitgelegd.


Overgangen tussen weergaven tussen documenten zijn beperkt tot navigatie met dezelfde oorsprong

Overgangen tussen weergaven tussen documenten zijn beperkt tot navigatie met dezelfde oorsprong . Een navigatie wordt als dezelfde oorsprong beschouwd als de oorsprong van beide deelnemende pagina's dezelfde is.

De oorsprong van een pagina is een combinatie van het gebruikte schema, de hostnaam en de poort, zoals 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.

U kunt bijvoorbeeld een overgang tussen documentweergaven maken wanneer u navigeert van developer.chrome.com naar developer.chrome.com/blog , aangezien deze van dezelfde oorsprong zijn. U kunt die overgang niet hebben als u van developer.chrome.com naar www.chrome.com navigeert, omdat deze cross-origin en dezelfde site zijn.


Overgangen tussen documentweergaven zijn opt-in

Om een ​​overgang tussen twee documenten tussen documenten te kunnen weergeven, moeten beide deelnemende pagina's zich hiervoor aanmelden. Dit gebeurt met de @view-transition at-regel in CSS.

Stel in de @view-transition at-regel de navigation in op auto om weergaveovergangen in te schakelen voor navigatie tussen verschillende documenten en met dezelfde oorsprong.

@view-transition {
  navigation: auto;
}

Door navigation in te stellen op auto geeft u toestemming voor het toestaan ​​van weergaveovergangen voor de volgende navigatietypes :

  • traverse
  • push of replace , als de activering niet door de gebruiker is geïnitieerd via de UI-mechanismen van de browser.

Navigaties die zijn uitgesloten van auto zijn bijvoorbeeld navigeren via de URL-adresbalk of klikken op een bladwijzer, evenals elke vorm van door de gebruiker of een script geïnitieerd herladen.

Als een navigatie te lang duurt (meer dan vier seconden in het geval van Chrome), wordt de weergaveovergang overgeslagen met een TimeoutError DOMException .

Demo voor overgangen tussen documenten

Bekijk de volgende demo waarin weergaveovergangen worden gebruikt om een ​​Stack Navigator-demo te maken. Er zijn hier geen oproepen naar document.startViewTransition() . De weergaveovergangen worden geactiveerd door van de ene pagina naar de andere te navigeren.

Opname van de Stack Navigator-demo . Vereist Chrome 126+.

Pas overgangen tussen documenten aan

Om de overgangen tussen documenten aan te passen, zijn er enkele webplatformfuncties die u kunt gebruiken.

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

Browserondersteuning

  • 124
  • 124
  • X
  • X

Bron

Om u in staat te stellen weergaveovergangen tussen documenten aan te passen, bevat de HTML-specificatie twee nieuwe gebeurtenissen die u kunt gebruiken: pageswap en pagereveal .

Deze twee gebeurtenissen worden geactiveerd voor elke navigatie tussen verschillende documenten met dezelfde oorsprong, ongeacht of er een weergaveovergang op het punt staat te gebeuren of niet. Als er tussen de twee pagina's een weergaveovergang gaat plaatsvinden, kunt u voor deze gebeurtenissen toegang krijgen tot het ViewTransition object met behulp van de eigenschap viewTransition .

  • De pageswap gebeurtenis wordt geactiveerd voordat het laatste frame van een pagina wordt weergegeven. U kunt dit gebruiken om op het laatste moment nog enkele wijzigingen aan te brengen op de uitgaande pagina, vlak voordat de oude snapshots worden gemaakt.
  • De pagereveal gebeurtenis wordt op een pagina geactiveerd nadat deze is geïnitialiseerd of opnieuw geactiveerd, maar vóór de eerste weergavemogelijkheid. Hiermee kunt u de nieuwe pagina aanpassen voordat de nieuwe snapshots worden gemaakt.

U 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 om de weergave-overgang aan te passen 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 in 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 gaan ook anders om met de verschillende beloften :

  • pageswap : Zodra het document verborgen is, wordt het oude ViewTransition object overgeslagen. Wanneer dat gebeurt, weigert viewTransition.ready en wordt viewTransition.finished opgelost.
  • pagereveal : De updateCallBack belofte is op dit punt al opgelost. U kunt gebruik maken van de beloften viewTransition.ready en viewTransition.finished .

Browserondersteuning

  • 123
  • 123
  • X
  • X

Bron

Bij zowel pageswap als pagereveal kunt u ook actie ondernemen op basis van de URL's van de oude en nieuwe pagina's.

In de MPA Stack Navigator hangt het type animatie dat u wilt gebruiken bijvoorbeeld af van het navigatiepad:

  • Wanneer u van de overzichtspagina naar een detailpagina navigeert, moet de nieuwe inhoud van rechts naar links schuiven.
  • Wanneer u van de detailpagina naar de overzichtspagina navigeert, moet de oude inhoud van links naar rechts naar buiten schuiven.

Hiervoor heeft u informatie nodig over de navigatie die, in het geval van pageswap , gaat plaatsvinden of, in het geval van pagereveal net heeft plaatsgevonden.

Hiervoor kunnen browsers nu NavigationActivation objecten weergeven die informatie bevatten over navigatie met dezelfde oorsprong. Dit object geeft het gebruikte navigatietype, de huidige en de eindbestemmingsgeschiedenisgegevens weer zoals gevonden in navigation.entries() van de Navigatie-API .

Op een geactiveerde pagina heeft u toegang tot dit object via navigation.activation . In het pageswap kunt u hiertoe toegang krijgen via e.activation .

Bekijk deze Profielen-demo die gebruikmaakt van NavigationActivation in de gebeurtenissen pageswap en pagereveal om de view-transition-name waarden in te stellen voor de elementen die moeten deelnemen aan de weergaveovergang.

Op die manier hoeft u niet elk item in de lijst vooraf te voorzien van een view-transition-name . In plaats daarvan gebeurt dit just-in-time met behulp van JavaScript, alleen op elementen die dit nodig hebben.

Opname van de Profiles-demo . Vereist Chrome 126+.

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 view-transition-name waarden te verwijderen nadat de view-overgang is uitgevoerd. Op deze manier is de pagina klaar voor opeenvolgende navigatie en kan deze ook de geschiedenis doorkruisen.

Om hierbij te helpen, gebruikt u deze 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 vorige 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 is geladen met weergaveblokkering

Browserondersteuning

  • 124
  • 124
  • X
  • X

Bron

In sommige gevallen wilt u misschien de eerste weergave van een pagina uitstellen totdat een bepaald element aanwezig is in de nieuwe DOM. Dit voorkomt knipperen en zorgt ervoor dat de status waarnaar u animeert stabiel is.

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 metatag.

<link rel="expect" blocking="render" href="#section1">

Deze metatag betekent dat het element aanwezig moet zijn in de DOM, niet dat de inhoud moet worden geladen. Bij afbeeldingen is bijvoorbeeld de aanwezigheid van de <img> -tag met de opgegeven id in de DOM-structuur voldoende om de voorwaarde als waar te laten evalueren. De afbeelding zelf kan nog steeds worden geladen.

Voordat u all-in gaat op het blokkeren van weergave, moet u zich ervan bewust zijn dat incrementele weergave een fundamenteel aspect van het web is, dus wees voorzichtig als u ervoor kiest om weergave te blokkeren. De impact van het blokkeren van weergave moet van geval tot geval worden beoordeeld. Vermijd standaard het gebruik van blocking=render tenzij u de impact die dit heeft op uw gebruikers actief kunt meten en peilen, door de impact op uw Core Web Vitals te meten.


Bekijk overgangstypen in overgangen tussen documenten

Weergaveovergangen tussen documenten ondersteunen ook typen weergaveovergangen om de animaties aan te passen en welke elementen worden vastgelegd.

Als u bijvoorbeeld naar de volgende of vorige pagina in een paginering gaat, wilt u mogelijk verschillende animaties gebruiken, afhankelijk van of u naar een hogere pagina of een lagere pagina in de reeks gaat.

Om deze typen vooraf in te stellen, voegt u de typen toe aan de @view-transition at-regel:

@view-transition {
  navigation: auto;
  types: slide, forwards;
}

Om de typen direct in te stellen, gebruikt u de gebeurtenissen pageswap en pagereveal 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 typen worden niet automatisch overgedragen van het ViewTransition object op de oude pagina naar het ViewTransition object van de nieuwe pagina. U moet bepalen welke type(n) u op zijn minst op de nieuwe pagina wilt gebruiken, zodat de animaties naar verwachting kunnen worden uitgevoerd.

Om op deze typen te reageren, gebruikt u de :active-view-transition-type() pseudo-klasse selector op dezelfde manier als bij weergave-overgangen van 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 typen automatisch opgeschoond wanneer een weergaveovergang is voltooid. Daarom werken typen goed met functies als BFCache .

Demo

In de volgende pagineringsdemo schuift de pagina-inhoud vooruit of achteruit op basis van het paginanummer waarnaar u navigeert.

Opname van de Paginatie-demo (MPA) . Er worden verschillende overgangen gebruikt, afhankelijk van naar welke pagina u gaat.

Het te gebruiken transitietype wordt bepaald in de pagereveal en pageswap gebeurtenissen door te kijken naar de van en naar URL's.

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 wordt altijd op prijs gesteld. Om te delen kunt u een probleem indienen bij de CSS Working Group op GitHub met suggesties en vragen. Geef uw probleem een ​​voorvoegsel met [css-view-transitions] . Mocht je een bug tegenkomen, dien dan een Chromium-bug in .