Всё, что нужно знать о View Transitions API в 2026 — от простых анимаций в одном документе до кросс-документных переходов между страницами и новейших scoped view transitions. Практические примеры кода от senior frontend разработчика.
Долгие годы плавные переходы между страницами были прерогативой JavaScript-библиотек и фреймворков. React Router анимации, Vue transition components, GSAP — всё это временные решения для отсутствующего в браузере примитива. CSS View Transitions API меняет это кардинально.
На май 2026 года View Transitions API готов к продакшену во всех основных браузерах. Переходы в одном документе (для SPA) работают в Chrome, Safari и Firefox. Кросс-документные view transitions — анимация между отдельными HTML-страницами при навигации — теперь доступны в Chromium и Safari, с Firefox на подходе. Scoped view transitions, анонсированные на Google I/O 2026, добавляют ограниченные переходы на уровне элементов для Canvas и SPA.
В этом руководстве я разбираю каждый аспект View Transitions API: базовый
startViewTransition(), кросс-документную навигацию через CSS правило
@view-transition, кастомные анимации с view-transition-name,
новые scoped transitions, таблицы поддержки браузеров и реальные паттерны, которые
можно использовать уже сегодня.
View Transitions API — это встроенный браузерный механизм для анимации изменений между двумя состояниями DOM. Он работает в трёх режимах:
document.startViewTransition(callback)
для анимации обновления DOM на одной странице.@view-transition или <meta> тегом запускает
автоматический переход.
Под капотом браузер делает снимок текущего состояния, позволяет обновить DOM,
затем делает снимок нового состояния и интерполирует между ними с помощью
CSS-анимаций. Браузер обрабатывает всю работу на уровне пикселей — никакого
requestAnimationFrame, ResizeObserver или ручной интерполяции.
Простейший пример — замена содержимого в div:
async function switchView() { // Захватываем состояние, обновляем DOM, анимируем const transition = await document.startViewTransition(async () => { // Ваша DOM-мутация contentDiv.innerHTML = newContent; }); // Ждём завершения анимации await transition.finished; }
Браузер захватывает состояние до (текущий DOM), выполняет callback (изменяет DOM), захватывает состояние после и запускает анимацию crossfade между двумя снимками.
Каждый view transition проходит через предсказуемый жизненный цикл:
transition.ready — разрешается, когда создано дерево псевдоэлементов
и анимации готовы к запуску.transition.finished — разрешается по завершении анимаций.transition.updateCallbackDone — разрешается после завершения callback
обновления DOM (до начала анимации).transition.skipTransition() — мгновенно переходит к новому состоянию без
анимации. Полезно для доступности — соблюдайте prefers-reduced-motion.Это функция, которая делает View Transitions API по-настоящему революционным. Кросс-документные view transitions позволяют анимировать навигацию между двумя отдельными HTML-страницами — настоящим multi-page приложением (MPA) — с плавным анимированным переходом.
Добавьте CSS правило @view-transition на обе страницы (исходящую и входящую):
/* На обеих страницах */ @view-transition { navigation: auto; }
Или используйте <meta> тег в <head>:
<meta name="view-transition" content="same-origin">
После включения все навигации между страницами одного origin будут автоматически анимироваться с crossfade-переходом. Обе страницы должны иметь правило — если только одна из них имеет, переход пропускается.
Настоящая магия происходит с общими элементами. Когда элемент существует
на обеих страницах (исходящей и входящей) с одинаковым view-transition-name,
браузер плавно анимирует его между старым и новым положением:
/* На странице A — изображение товара в карточке */ .product-image-main { view-transition-name: product-image; } /* На странице B — то же изображение на позиции hero */ .product-detail-image { view-transition-name: product-image; }
При навигации со страницы каталога на страницу товара изображение плавно масштабируется и перемещается из карточки в позицию hero. Остальное содержимое страницы просто перекрестно затухает. Никакого JavaScript не требуется.
Стандартный crossfade чистый, но универсальный. Вы можете настроить каждый аспект
анимации с помощью CSS псевдоэлементов и @keyframes.
Во время view transition браузер создаёт дерево псевдоэлементов:
::view-transition — корневой оверлей (покрывает всю страницу)::view-transition-group(name) — группа для каждого именованного элемента::view-transition-image-pair(name) — содержит старый и новый снимки::view-transition-old(name) — снимок исходящего состояния::view-transition-new(name) — снимок входящего состоянияАнимация slide-and-fade для всей страницы:
::view-transition-old(root) { animation-duration: 400ms; animation-name: slide-out; } ::view-transition-new(root) { animation-duration: 400ms; animation-name: slide-in; } @keyframes slide-out { 0% { opacity: 1; transform: translateX(0); } 100% { opacity: 0; transform: translateX(-30px); } } @keyframes slide-in { 0% { opacity: 0; transform: translateX(30px); } 100% { opacity: 1; transform: translateX(0); } }
Всегда добавляйте fallback для пользователей, предпочитающих уменьшенную анимацию:
@media (prefers-reduced-motion: reduce) { ::view-transition-old(root), ::view-transition-new(root) { animation-duration: 0.01ms !important; } }
Анонсированные на Google I/O 2026, scoped view transitions позволяют ограничить переход конкретным DOM-элементом вместо всего документа. Это критическое улучшение для:
Передайте опцию scope в startViewTransition():
const contentArea = document.getElementById('main-content'); await document.startViewTransition({ update: async () => { contentArea.innerHTML = newContent; }, scope: contentArea }).finished;
| Функция | Chrome | Edge | Safari | Firefox |
|---|---|---|---|---|
| В одном документе (startViewTransition) | 111+ | 111+ | 18+ | 121+ |
| Кросс-документные (meta/@view-transition) | 126+ | 126+ | 18+ | 131+ (частично) |
| Scoped transitions (один документ) | 148+ | 148+ | — | — |
| Scoped transitions (кросс-документ) | 150+ | 150+ | — | — |
| Кастомные анимации (::view-transition-old/new) | 111+ | 111+ | 18+ | 121+ |
| view-transition-name на нескольких элементах | 111+ | 111+ | 18+ | 121+ |
Для React, Vue или Svelte оберните роутер в startViewTransition():
// React Router интеграция import { useNavigate } from 'react-router-dom'; function useViewTransitionNavigate() { const navigate = useNavigate(); return async (to, options) => { if (document.startViewTransition) { await document.startViewTransition(async () => { navigate(to, options); }).finished; } else { navigate(to, options); } }; }
Классический сценарий — миниатюра, которая расширяется в полноразмерное изображение.
Обе используют одинаковый view-transition-name:
/* Миниатюра в галерее */ .gallery-thumb[data-id="photo-1"] { view-transition-name: gallery-photo-1; } /* Hero-изображение на странице деталей */ .photo-hero[data-id="photo-1"] { view-transition-name: gallery-photo-1; }
Используйте scoped view transitions для контентных панелей табов. Только содержимое панели анимируется, остальная страница статична:
async function switchTab(tabIndex) { const panel = document.getElementById(`tab-panel-${tabIndex}`); await document.startViewTransition({ update: async () => { panels.forEach(p => p.classList.remove('active')); panel.classList.add('active'); }, scope: panel.parentElement }).finished; }
View Transitions удивительно эффективны, но есть важные факторы:
startViewTransition(). Последовательные переходы вызывают мерцание.View Transitions API — это progressive enhancement. Ваша страница должна отлично работать и без него:
Нужны плавные переходы? Смотрите мои услуги разработки сайтов
if ('startViewTransition' in document) { await document.startViewTransition(async () => { updateDOM(); }).finished; } else { updateDOM(); }
document.startViewTransition(callback), где callback изменяет DOM. API захватывает текущее состояние страницы, выполняет callback, захватывает новое состояние и анимирует между ними. Пример: await document.startViewTransition(() => { updateUI(); }).finished;<meta name="view-transition" content="same-origin"> на обе страницы, и браузер автоматически анимирует переход. Обе страницы должны быть одного origin. Для сравнения SPA и MPA архитектур смотрите моё руководство по разработке веб-приложений.document.startViewTransition({ update: callback, scope: element }).::view-transition-old и ::view-transition-new вместе с @keyframes анимациями. Вы можете переопределить animation-duration, animation-timing-function и animation-name. Используйте view-transition-name для анимации общих элементов. Для плавных цветовых переходов между темами используйте CSS Relative Color Syntax — он позволяет создавать динамические цвета на основе CSS-переменных.<meta> тега или CSS правила @view-transition переходы при навигации работают без JavaScript. Переходы в одном документе (startViewTransition) требуют JavaScript, так как обновление DOM нуждается в скриптах.Вот простейшая реализация — плавное переключение тёмной темы:
<button id="themeToggle">Сменить тему</button> <script> document.getElementById('themeToggle').addEventListener('click', async () => { await document.startViewTransition(async () => { document.body.classList.toggle('dark-mode'); }).finished; }); </script>
Для кросс-документных переходов просто добавьте на страницы:
<meta name="view-transition" content="same-origin">
И все навигации между страницами с этим тегом будут анимироваться с плавным crossfade. View Transitions API — одно из самых значительных добавлений в веб-платформу последних лет.
Нужна помощь с внедрением view transitions в вашем проекте? Я занимаюсь frontend-архитектурой и разработкой. Посмотрите мои услуги или свяжитесь со мной. Для более широкого обзора современных CSS-возможностей читайте моё руководство по CSS Container Queries.
Я разрабатываю production-приложения с использованием новейших CSS и JavaScript API. Обсудим ваш проект — бесплатно.