Перейти к содержимому

21. View Transitions

View Transitions — это мощный API браузера, который позволяет создавать плавные анимированные переходы между страницами, превращая обычный многостраничный сайт в приложение с ощущением SPA. Astro делает работу с этим API невероятно простой.

Традиционная навигация между страницами сопровождается резкой перезагрузкой — браузер стирает одну страницу и рисует другую. View Transitions API позволяет браузеру сначала создать «снимок» текущего состояния, затем загрузить новую страницу, и плавно анимировать переход между двумя состояниями.

Astro поддерживает View Transitions через специальный компонент и набор директив, которые работают как в режиме MPA (Multi-Page Application), так и помогают создавать SPA-подобный опыт.

Для включения View Transitions достаточно добавить компонент в секцию <head> вашего базового макета:

---
import { ViewTransitions } from 'astro:transitions';
---
<html>
<head>
<ViewTransitions />
</head>
<body>
<slot />
</body>
</html>

После этого Astro автоматически перехватывает все навигационные ссылки и применяет анимации при переходах. По умолчанию используется анимация fade — элементы плавно появляются и исчезают.

Директива transition:name — сопоставление элементов

Заголовок раздела «Директива transition:name — сопоставление элементов»

Одна из самых впечатляющих возможностей — это анимация «общих элементов» между страницами. Если на двух страницах есть элементы с одинаковым transition:name, браузер создаст плавную анимацию морфинга от одного к другому:

<!-- Страница со списком статей -->
<img src={post.image} transition:name={`hero-${post.slug}`} />
<!-- Страница статьи -->
<img src={post.image} transition:name={`hero-${post.slug}`} />

Теперь при переходе на страницу статьи изображение «перелетит» из своей позиции в списке на новое место — это создаёт эффект непрерывности интерфейса.

Astro поставляется с набором готовых анимаций:

---
import { fade, slide, morph } from 'astro:transitions';
---
<!-- Плавное появление/исчезновение -->
<div transition:animate="fade">Контент</div>
<!-- Слайд слева/справа -->
<main transition:animate="slide">Основной контент</main>
<!-- Умный морфинг с учётом позиции -->
<article transition:animate={morph()}>Статья</article>
<!-- Кастомная конфигурация fade -->
<section transition:animate={fade({ duration: '0.5s' })}>
Медленное появление
</section>

Можно полностью управлять анимацией через CSS-переменные и @keyframes. Astro использует два псевдоэлемента ::view-transition-old и ::view-transition-new для управления переходом:

/* Пользовательская анимация "листание страниц" */
@keyframes slide-from-right {
from { transform: translateX(100%); opacity: 0; }
}
@keyframes slide-to-left {
to { transform: translateX(-100%); opacity: 0; }
}
::view-transition-old(main-content) {
animation: 300ms ease slide-to-left;
}
::view-transition-new(main-content) {
animation: 300ms ease slide-from-right;
}

Некоторые элементы не должны перезагружаться при навигации — например, аудиоплеер или боковая панель с состоянием. Директива transition:persist сохраняет элемент «живым» между страницами:

<!-- Аудиоплеер не прерывается при навигации -->
<audio-player transition:persist>
<audio src="/podcast.mp3" />
</audio-player>
<!-- Сохраняем и id для точного сопоставления -->
<aside transition:persist="sidebar">
<Navigation />
</aside>

Для улучшения UX можно добавить полосу прогресса загрузки. Astro предоставляет хуки жизненного цикла через события document:

src/scripts/progress.ts
document.addEventListener('astro:before-preparation', () => {
document.querySelector('#progress-bar')?.classList.add('loading');
});
document.addEventListener('astro:page-load', () => {
document.querySelector('#progress-bar')?.classList.remove('loading');
});