Tradycyjne MPA, czyli Multi-Page Application, to architektura, w której każda podstrona to osobny dokument HTML ładowany od serwera przy nawigacji. — każde kliknięcie to pełny reload. Szybko, przewidywalnie, ale wizualnie szorstko. Astro View Transitions API pozwala przeglądarce animować przejście między dwoma widokami dokumentu zamiast pokazywać gwałtowną podmianę strony. łączy oba światy: animowane przejścia jak w SPA (Single Page Application) to aplikacja webowa, w której cała strona renderuje się i działa po stronie przeglądarki w jednym dokumencie HTML — typowe podejście Reacta, Vue czy Angulara bez SSR., prosta architektura MPA, zero kompromisów wydajnościowych.
Skąd się wziął View Transitions API
View Transitions to natywne API przeglądarki, które pozwala animować przejścia między stanami DOM. Początkowo było zaimplementowane tylko w Chrome (2023), potem dołączyło Safari (17.4+, marzec 2024), a Firefox dodał natywne wsparcie dopiero w wersji 144 (październik 2025) — i to najpierw dla przejść w obrębie jednego dokumentu. Dla przeglądarek bez natywnego API Astro robi Graceful degradation to podejście, w którym aplikacja w razie awarii części funkcji nadal działa w okrojonym, ale użytecznym zakresie — zamiast wywalać się w całości. Tu: gdy pada jedno API, pokazujemy zastępczy komunikat, a reszta strony działa dalej. — zwykły reload strony, bez animacji, ale też bez błędów.
Astro było jednym z pierwszych frameworków, które zintegrowały View Transitions w sposób end-to-end. Do Astro 4 komponent nazywał się <ViewTransitions />. W Astro 5.0 został przemianowany na <ClientRouter />, żeby lepiej odzwierciedlać zakres działania (to klient-side router, który wykorzystuje View Transitions tam, gdzie to możliwe) — stara nazwa działała jeszcze jako alias z ostrzeżeniem o wycofaniu. Astro 6.0 usunęło <ViewTransitions /> całkowicie, więc na bieżących wersjach stosujemy <ClientRouter />.
Setup — trzy linie kodu
Żeby dodać View Transitions do całej strony, dodajesz jedną rzecz w layoucie:
Po dodaniu <ClientRouter /> Astro automatycznie przechwytuje kliknięcia w linki wewnętrzne i zamiast pełnego reloadu robi animowane przejście z wykorzystaniem View Transitions API (jeśli przeglądarka wspiera) lub soft-reload (jeśli nie).
To wszystko. Bez zmian w stronach, bez konfiguracji, bez bibliotek zewnętrznych.
Co dokładnie się dzieje pod maską
Kiedy user klika link wewnętrzny:
- Astro przechwytuje kliknięcie przez event listener.
- Pobiera nową stronę przez
fetch(). - Uruchamia
document.startViewTransition()(lub fallback). - Podmienia
<body>na nową treść. - Przeglądarka animuje przejście — domyślnie Cross-fade to płynne przenikanie, w którym stary widok zanika, a nowy jednocześnie się pojawia..
Efekt — user widzi płynne przejście zamiast białego błysku reloadu. Nawigacja wstecz/do przodu w przeglądarce też działa z animacjami.
Named transitions — precyzyjne animacje dla wybranych elementów
Sam cross-fade jest fajny, ale prawdziwą wartość View Transitions zyskują, kiedy dodajesz named transitions — oznaczone elementy, które mają animować między stronami w skoordynowany sposób.
Weźmy typowy przykład — lista artykułów i strona pojedynczego artykułu. Chcesz, żeby po kliknięciu miniaturka obrazu „powiększyła się" do pełnowymiarowego obrazu hero na nowej stronie.
Kluczem do sukcesu jest to samo transition:name na obu stronach. Przeglądarka widzi, że element hero-post-123 istnieje na stronie A i B, i automatycznie animuje przejście między pozycjami i rozmiarami.
Dla bloga ze zdjęciami efekt jest natychmiastowy: tapnąć miniaturkę, płynna ekspansja do pełnego hero artykułu. Wizualnie nieodróżnialne od natywnej aplikacji iOS/Android.
Persistent state — zachowanie stanu przy nawigacji
Kolejny problem nawigacji MPA — tracisz stan elementów pomiędzy stronami. Formularz kontaktowy, audio player, kontrolki video — wszystko resetuje się przy reloadzie.
Astro daje transition:persist:
Element oznaczony transition:persist nie jest zniszczony między stronami — zachowuje swój stan (pozycja odtwarzania, focus, wartość inputa). User może słuchać podcastu w headerze i przechodzić między artykułami bez przerywania odtwarzania.
Typowe zastosowania to player audio lub video, formularze wieloetapowe (jeśli nie zmieniają się między stronami), widgety czatu i koszyk w e-commerce — wszędzie tam, gdzie reset stanu przy nawigacji jest prawdziwym problemem użytkownika.
Dyrektywy animacji — dostosowanie efektu
Domyślny cross-fade działa w większości przypadków, ale możesz wybrać inny preset:
Dostępne presety:
fade— cross-fade (domyślny)slide— wsunięcie z prawej/lewejnone— brak animacji- Custom — własna animacja CSS
Custom animation:
Albo całkowicie własna, z keyframe'ami:
Selektory ::view-transition-old i ::view-transition-new to natywne API przeglądarki — możesz stylować przejścia jak każdy inny element CSS.
Lifecycle events — reagowanie na zmiany strony
ClientRouter emituje eventy, które pozwalają reagować na nawigację:
To przydaje się szczególnie przy re-inicjalizacji skryptów analitycznych (GA, Plausible) po nowej stronie, re-aplikowaniu motywu (dark/light) po nawigacji i trackingu konwersji.
Pułapki i ograniczenia
1. Scroll position. Domyślnie Astro resetuje scroll do góry przy nawigacji, ale jeśli chcesz zachować pozycję scrollowania (np. przy kliknięciu w sekcję w tej samej stronie), musisz to obsłużyć ręcznie.
2. Skrypty globalne. Skrypty w <head> ładowane są raz. Jeśli zainicjowałeś coś (np. Intersection Observer) na stronie A, po przejściu na B trzeba to zainicjować ponownie — stąd event astro:page-load.
3. Forms. ClientRouter obsługuje formularze GET i POST, ale przy krytycznych flow (płatność, logowanie, upload pliku) często lepiej dodać data-astro-reload, żeby zachować klasyczne zachowanie przeglądarki.
4. Third-party widgets. Widgety wstrzykujące treść do DOM (np. komentarze Disqus, social embeds) często nie lubią podmiany <body>. Oznacz je transition:persist lub reinicjalizuj na astro:page-load.
5. Przeglądarki bez pełnego wsparcia. Astro ma strategie fallbacku dla przeglądarek bez natywnego View Transitions API. UX pozostaje poprawny, ale animacje nie muszą być identyczne między silnikami.
Dostępność i skrypty po nawigacji
View Transitions wyglądają jak warstwa wizualna, ale technicznie zmieniają sposób, w jaki strona reaguje po kliknięciu linku. Dlatego wdrożenie powinno mieć krótką checklistę dostępności i utrzymania skryptów.
Każda strona musi mieć sensowny <title> i główny <h1>, bo ClientRouter używa ich do ogłaszania zmiany trasy technologiom wspomagającym — bez tego użytkownik czytnika ekranu nie wie, że nawigacja w ogóle nastąpiła. Astro respektuje prefers-reduced-motion to ustawienie systemowe, którym użytkownik sygnalizuje, że chce ograniczyć animacje i ruch w interfejsie., ale własne animacje CSS też muszą mieć wariant ograniczonego ruchu — systemowe preferencje użytkownika powinny wygrywać z estetyką strony. Skrypty inicjalizujące obserwatory, tooltipy, galerie albo analytics uruchamiaj po astro:page-load, a nie tylko przy pierwszym ładowaniu dokumentu. Elementy z dużym stanem (player audio, koszyk) oznaczaj transition:persist tylko wtedy, gdy naprawdę mają przetrwać zmianę strony. Linki do krytycznych procesów, paneli zewnętrznych i formularzy transakcyjnych oznacz data-astro-reload.
SEO — czy View Transitions nie zaszkodzą?
Obawa, która regularnie wraca: „Skoro Astro podmienia <body> przez JS, czy Google widzi wszystko?"
Odpowiedź: tak, widzi. View Transitions działają po załadowaniu statycznego HTML-a dla docelowej strony. Jeśli Google crawler wchodzi bezpośrednio na /blog/moj-wpis/, dostaje pełny, statyczny HTML — dokładnie tak samo, jakby ClientRouter nie istniał. Animacje są tylko warstwą UX dla użytkownika klikającego linki wewnętrzne.
Więcej o SEO w Astro piszę w osobnym artykule.
Kiedy NIE używać View Transitions
View Transitions to dobre narzędzie, ale nie każde środowisko na nie zasługuje. Jeśli strona to głównie workflow z formularzami wieloetapowymi, ClientRouter komplikuje stan bardziej, niż wart jest efekt wizualny — w takim przypadku lepiej rozważyć czysty SPA (React/Next.js) albo Astro bez ClientRouter. Podobnie gdy wiele komponentów dzieli stan: MPA + View Transitions to antywzorzec, a nie usprawnienie. ClientRouter waży ~4 KB JS, więc dla landing page'a z jednym CTA, gdzie każdy kilobajt jest na wagę złota, można go spokojnie pominąć.
Dla bloga, portfolio, dokumentacji, strony firmowej czy lekkiego e-commerce View Transitions są wygraną bezsporną — i to jedną z tych rzadkich, gdzie dodanie funkcji jednocześnie poprawia wydajność postrzeganą przez użytkownika.
Porównanie z SPA
Pytanie, które dostaję regularnie: „Skoro Astro + View Transitions daje płynne przejścia, to po co w ogóle SPA?"
Odpowiedź zależy od charakteru aplikacji. Jeśli to treść z nawigacją, w której strony są de facto niezależne — Astro z View Transitions jest prostsze, szybsze i wydajniejsze niż Next.js SPA. Jeśli to aplikacja z dużym, współdzielonym state'em, gdzie użytkownik spędza czas w jednej „sesji" — SPA nadal ma przewagę.
Szczegółowe porównanie obu podejść znajdziesz w artykule o Astro vs Next.js.
