Wyświetlanie przejść w aplikacjach jednostronicowych

Częstym wzorcem w przypadku stron internetowych jest używanie JavaScriptu do dynamicznego zastępowania treści na stronie bez wczytywania nowego, pełnego dokumentu HTML. Jest to tzw. aplikacja na jednej stronie (SPA). Przejścia widoku umożliwiają zachowanie ciągłości lub kontekstu między stronami w aplikacji SPA.

Przejścia między pełnymi stronami

Gdy użytkownik przechodzi do nowego widoku w aplikacji SPA, framework zastępuje DOM nową treścią. W ten sposób treść po prostu się pojawi, ale co zrobić, jeśli chcesz zapewnić przejście między bieżącą a nową treścią?

Przejścia często pokazują jednocześnie stary i nowy widok, np. stary widok zanika, a nowy się pojawia. Zastępowanie istniejących treści było przed wprowadzeniem przejść widoku trudne.

Aby używać przejść widoku, musisz umieścić logikę zmiany DOM w funkcji zwrotnej. W tych przykładach mamy podstawową implementację routera udostępnianą przez komponent internetowy o nazwie MyRouter. Sposób włączania przejść widoku zależy od używanego routera i frameworka.

document.startViewTransition(() => updateTheDOMSomehow());

Umożliwia to domyślne przejście, które powoduje zanikanie starego widoku i pojawianie się nowego.

Co się tutaj dzieje? Gdy klikniesz document.startViewTransition(), przeglądarka zrobi zrzut ekranu starego widoku. Następnie wywołuje przekazaną przez Ciebie funkcję wywołania zwrotnego, która aktualizuje DOM do nowego widoku (ale jeszcze go nie wyświetla). Po zakończeniu działania funkcji wywołania zwrotnego przeglądarka rozpoczyna przejście do nowej treści.

// Fallback for browsers that don't support this API:
if (!document.startViewTransition) {
  updateTheDOMSomehow();
  return;
} else {
  // With a View Transition:
  document.startViewTransition(() => updateTheDOMSomehow());
}

Dostosowywanie przejścia

Jak widać w poprzednim przykładzie, domyślne przejście widoku powoduje zanikanie starego widoku i pojawianie się nowego. Możesz dostosować przejście, aby lepiej pasowało do stylu Twojej witryny, poprzez stylizowanie pseudoelementów generowanych przez przejścia widoku.

Przejście wyjścia możesz określić za pomocą parametru ::view-transition-old(), a przejście wejścia za pomocą parametru ::view-transition-new(). Możesz też określić wartości obu tych parametrów za pomocą parametru ::view-transition-group().

W tym przykładzie stary widok zostanie wycofany za pomocą przejścia slide-out-to-left, a nowy widok zostanie wprowadzony za pomocą przejścia slide-in-from-right. Oba będą trwały 200 milisekund.

::view-transition-group(root){
  animation-duration: 200ms;
}

::view-transition-old(root) {
  animation-name: slide-out-to-left;
}

::view-transition-new(root) {
  animation-name: slide-in-from-right;
}

Różne przejścia w zależności od kontekstu

Możesz chcieć używać różnych przejść w zależności od tego, co robi użytkownik. Jeśli np. kliknięcie linku na stronie głównej powoduje, że nowy widok pojawia się z prawej strony, kliknięcie linku, który ma spowodować powrót na stronę główną, powinno spowodować, że widok strony głównej pojawi się z lewej strony.

Różne animacje możesz określić za pomocą pseudoklasy :active-view-transition-type().

html:active-view-transition-type(forwards) {
  &::view-transition-old(root) {
    animation-name: slide-out-to-left;
  }

  &::view-transition-new(root) {
    animation-name: slide-in-from-right;
  }
}

Następnie możesz wybrać typ przejścia widoku, który ma być używany podczas wywoływania funkcji document.startViewTransition().

const direction = next === 'home' ? 'backwards' : 'forwards';

document.startViewTransition({
  update: updateTheDOMSomehow,
  types: [direction],
});

Przejścia określonych elementów

Do tej pory stosowaliśmy przejście tylko do elementu głównego, aby przejście obejmowało cały widok. Możesz jednak używać przejść widoku do animowania określonych części stron.

Może się na przykład zdarzyć, że treści w starym widoku będą pasować do treści w nowym widoku. Może to być tytuł treści lub obraz. Może to być nawet miniatura w starym widoku i film w nowym widoku.

Najpierw musisz określić elementy, które mają podlegać przejściu, za pomocą właściwości view-transition-name. Aby przejścia widoku działały, dla każdego elementuview-transition-name musi być dokładnie 1 element przed wywołaniem funkcji document.startViewTransition() i dokładnie 1 element po zakończeniu wywołania zwrotnego w funkcji document.startViewTransition().

W tym przykładzie znajduje się odtwarzacz muzyki, który wyświetla okładkę albumu, tytuł i wykonawcę. Widok alternatywny przedstawia te same treści w innej kolejności, z dodatkiem tekstu utworu.

W poprzednim przykładzie w starym i nowym widoku znajduje się dokładnie po jednym elemencie, który uległ zmianie, a nawet mają one te same selektory. Elementy, na których zastosowano przejście, wydają się zmieniać rozmiar i położenie. Nieprzekształcone części widoku pojawiają się i znikają.

Przyjrzyjmy się bardziej złożonemu przykładowi. Na przykład na stronie głównej bloga może być widoczny nagłówek i obraz każdego posta, które są też widoczne w pełnym widoku strony posta na blogu. Podczas przechodzenia ze strony głównej do konkretnego posta możesz sprawić, że tytuł i obraz będą się przesuwać do nowego miejsca, aby zapewnić kontekst.

Aby to zrobić w przypadku tytułu, musisz mieć w elemencie tytułu symbol view-transition-name, który jest unikalny w starym widoku, wspólny z elementem tytułu w nowym widoku i unikalny w nowym widoku. Jest to trudne, ponieważ strona główna zawiera wiele nagłówków i obrazów, a Ty nie wiesz, który z nich kliknie użytkownik.

Możesz to zrobić na 2 sposoby. Możesz dodać unikalny element view-transition-name do każdego posta na stronie głównej, a następnie dopasować tę nazwę do każdego posta na pełnej stronie. Możesz je wygenerować za pomocą identyfikatora posta. Możesz też użyć ogólnego parametru view-transition-name, ale tylko po kliknięciu posta przez użytkownika i przed wywołaniem funkcji document.startViewTransition().

Projektowanie przejść

Przejścia widoku to zestaw narzędzi, których możesz używać, aby prowadzić użytkowników i dostarczać dodatkowe wskazówki dotyczące marki lub kontekstu. Aby znaleźć przejścia, które sprawdzą się w Twojej witrynie, prawdopodobnie zastosujesz kilka technik.

W zależności od efektu, jaki chcesz uzyskać, może być konieczne dostosowanie elementów lub animacji. W poprzednim przykładzie dostosowano kilka stylów, aby uzyskać płynne przejścia.

Nagłówek ma regułę width: fit-content, która jest przydatna, gdy przenosisz tekst, który się nie zawija (lub ma takie samo zawijanie w starym i nowym widoku). W przeciwnym razie przejście może odbywać się między elementami o różnej szerokości, co sprawi, że będzie mniej płynne.

Obraz ma też inne proporcje w starym i nowym widoku. W tym przykładzie zmodyfikowano animację i właściwość object-fit, aby przejście było płynne.

Szacunek dla prefers-reduced-motion

Użytkownicy często proszą o ograniczenie ruchu, ponieważ animacje pełnoekranowe, takie jak te, które można uzyskać za pomocą przejść widoku, mogą powodować dyskomfort u osób z zaburzeniami równowagi. Animacje możesz wyłączyć za pomocą zapytania o media prefers-reduced-motion. Możesz też wybrać alternatywne animacje, które są bardziej subtelne, ale nadal pokazują, jak elementy są ze sobą połączone.

@media (prefers-reduced-motion) {
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) {
    animation: none !important;
  }
}

Sprawdź swoją wiedzę

Jak nazywa się pseudoelement reprezentujący widok przed wywołaniem funkcji document.startViewTransition()?

::view-transition-previous
Źle.
::view-transition-prior
Źle.
::view-transition-old
Dobrze!
::view-transition-initial
Źle.

Jaka jest domyślna animacja przejścia widoku?

Zanikanie starego obrazu podczas pojawiania się nowego
Dobrze!
Przesuń od lewej do prawej
Źle.
Przejście ze starego obrazu w biel, a następnie w nowy
Źle.
Przejście z gwiazdką
Źle.

Jaki jest domyślny view-transition-name strony?

document
Źle.
shadow-root
Źle.
root
Dobrze!
body
Źle.