Что такое View Transitions в Astro и как их включить?
View Transitions — API браузера для анимированных переходов между страницами без полной перезагрузки. В Astro включаются добавлением компонента <ViewTransitions /> в <head> layout и директив transition:* на элементах.
Что такое View Transitions
View Transitions — стандартный браузерный API (Chrome 111+, поддержан через полифил в остальных), позволяющий анимировать переход между двумя состояниями DOM без полной перезагрузки страницы. В Astro это реализовано поверх стандартного API с добавлением маршрутизации на стороне клиента: при клике по ссылке Astro перехватывает навигацию, загружает новую страницу через fetch и применяет CSS-анимацию перехода между старым и новым DOM-деревом.
Включение View Transitions
Достаточно импортировать компонент ViewTransitions и поместить его в <head> базового layout:
---
// src/layouts/BaseLayout.astro
import { ViewTransitions } from 'astro:transitions';
---
<html lang="ru">
<head>
<meta charset="UTF-8" />
<title>Мой сайт</title>
<ViewTransitions />
</head>
<body>
<slot />
</body>
</html>
После этого все навигации между страницами, использующими этот layout, становятся анимированными. По умолчанию применяется анимация fade.
Именованные переходы с transition:name
Директива transition:name позволяет браузеру плавно «перелетать» конкретный элемент с одной страницы на другую — это называется shared element transition:
---
// src/pages/index.astro
const posts = await getCollection('blog');
---
{posts.map(post => (
<a href={`/blog/${post.slug}`}>
<img
src={post.data.cover}
alt={post.data.title}
transition:name={`cover-${post.slug}`}
/>
<h2 transition:name={`title-${post.slug}`}>{post.data.title}</h2>
</a>
))}
---
// src/pages/blog/[slug].astro
const { post } = Astro.props;
---
<img
src={post.data.cover}
alt={post.data.title}
transition:name={`cover-${post.slug}`}
/>
<h1 transition:name={`title-${post.slug}`}>{post.data.title}</h1>
Управление анимацией: transition:animate
Директива transition:animate задаёт тип анимации для элемента или всей страницы:
import { slide, fade, none } from 'astro:transitions';
<!-- Весь main скользит при переходе -->
<main transition:animate={slide()}>>
<slot />
</main>
<!-- Навигация не анимируется -->
<nav transition:animate={none()}>>
...
</nav>
<!-- Кастомная анимация -->
<section transition:animate={{
forwards: {
old: [{ opacity: 1 }, { opacity: 0 }],
new: [{ opacity: 0 }, { opacity: 1 }],
easing: 'ease-in-out',
duration: '0.3s'
},
backwards: {
old: [{ opacity: 1 }, { opacity: 0 }],
new: [{ opacity: 0 }, { opacity: 1 }]
}
}}>
События жизненного цикла
Astro генерирует события на document, которые можно слушать для выполнения JS-логики при переходах:
// src/scripts/analytics.js
document.addEventListener('astro:page-load', () => {
// Вызывается после каждого перехода и при первой загрузке
console.log('Страница загружена:', window.location.pathname);
initAnalytics();
});
document.addEventListener('astro:before-preparation', (event) => {
// event.from — текущий URL, event.to — целевой URL
// Можно отменить переход: event.preventDefault()
});
document.addEventListener('astro:after-swap', () => {
// Новый DOM уже вставлен, но анимация ещё идёт
restoreFocusState();
});
Директива transition:persist
Элементы с transition:persist сохраняются между переходами без пересоздания — полезно для аудиоплееров, видео, состояния форм:
<video src="/podcast.mp3" transition:persist controls />
Подводные камни
- View Transitions поддерживаются нативно только в Chromium-браузерах; Firefox и Safari используют полифил Astro, который работает через fade без CSS-анимаций браузера — визуальный результат отличается.
transition:nameдолжен быть уникальным на каждой странице в каждый момент времени — дублирующиеся имена приводят к непредсказуемой анимации или её отсутствию.- Скрипты, вставленные через обычные
<script>-теги, не перевыполняются при переходе — нужно слушать событиеastro:page-loadдля инициализации JS после навигации. - Компоненты React/Vue/Svelte теряют своё состояние при переходе, если не используется
transition:persist— это нарушает ожидания при работе с управляемыми формами или другим интерактивным состоянием. - Анимации из CSS
@keyframes, заданные черезtransition:animateна элементах сtransition:name, могут конфликтовать с браузерным анимированием shared-элементов. - Хэш-навигация (
#anchor) по умолчанию не запускает View Transition — нужно явно обрабатывать этот случай. - При использовании
transition:persistна компонентах с серверными пропсами — данные не обновляются при переходе, что приводит к устаревшему содержимому. - Если layout-компонент не является общим для обеих страниц, переход между ними не будет иметь анимации — стоит убедиться, что оба маршрута используют одинаковый layout с
ViewTransitions.
Common mistakes
- Полагаться, что View Transitions API доступен везде — нужен fallback.
- Забывать переинициализировать сторонние библиотеки после
astro:after-swap. - Использовать одинаковые
transition:nameдля не связанных элементов.
What the interviewer is testing
- Знает компонент
<ClientRouter />и его роль. - Понимает атрибуты
transition:name,transition:persist. - Помнит про события lifecycle перехода.