- PVSM.RU - https://www.pvsm.ru -

View Transitions API: полное руководство по плавным переходам в браузере

View Transitions API: полное руководство по плавным переходам в браузере - 1

Помните 2015 год? Тогда Пол Льюис из Google представил концепцию FLIP [1] (First, Last, Invert, Play) — революционный на тот момент способ делать анимации интерфейса со стабильными 60 fps. Идея была гениальной: вместо того, чтобы анимировать свойства разметки (width, top), мы измеряем начальное и конечное состояние элементов, а затем анимируем только transform.

В теории звучало отлично, но на практике реализация была трудоёмкой: требовались вычисления координат getBoundingClientRect, ручной контрольrequestAnimationFrame и бесконечные вычисления таймингов. В итоге большинство разработчиков просто отказывались от сложных переходов, потому что цена поддержки такого кода была слишком высока.

Прошло восемь лет, и в Chrome 111 появился View Transitions API [2]. По сути, браузер наконец-то научился делать FLIP за нас. API решает те же задачи, что FLIP, но принципиально другим способом. Джейк Арчибальд на Chrome Dev Summit [3] показал, как три строчки нативного кода заменяют сотни строк самописных скриптов.

Давайте разберёмся, как это работает, где подводные камни и можно ли использовать в рабочей среде прямо сейчас?

Зачем нам ещё один API?

Если вы когда-либо пользовались веб-приложениями на iOS или Android, вы видели этот эффект: нажимаете на карточку товара, и картинка плавно «перелетает» на страницу деталей, превращаясь в заголовок. В вебе повторить такое было мучительно сложно.

Вы можете сказать: «У нас же есть CSS Transitions и Web Animations API (WAAPI), зачем ещё один?» Разница фундаментальна: старые методы анимируют элементы, а View Transitions API анимирует состояния.

Вот наглядное сравнение:

Задача

CSS Transitions

Web Animations API

View Transitions API

Анимация layout-свойств

Дёргается

Дёргается

Плавно*

Shared elements

Невозможно

Сложно

Из коробки

Кросс-документные переходы

Нет

Нет

Да

Синхронизация состояний

Вручную

Вручную

Автоматически

*Плавно, так как анимируются снимки, а не layout

Чтобы эффективно использовать API, нужно понимать, как браузер организует переход изнутри.

Ключевые концепции: снимки, псевдоэлементы и жизненный цикл

Когда вы вызываете startViewTransition(), браузер проходит чёткую последовательность: захватывает снимки элементов с view-transition-name, выполняет ваш callback с изменениями DOM, захватывает снимки нового состояния и создаёт дерево псевдоэлементов:

::view-transition
::view-transition-group(name)
 		 ::view-transition-image-pair(name)
 ::view-transition-old(name)   /* снимок ДО */
     			 ::view-transition-new(name)   /* снимок ПОСЛЕ */
View Transitions API: полное руководство по плавным переходам в браузере - 2 [4]

Поскольку мы манипулируем «картинками» (снимками), а не живыми DOM-узлами, анимация, как правило, выполняется на уровне композитора. Отсюда и стабильная производительность.

Быстрый старт: минимальный рабочий пример

Давайте посмотрим на код, как внедрить View Transitions в существующий проект. Это на самом деле проще, чем кажется.

Представьте типичную ситуацию в SPA: у вас есть функция, которая получает новый контент и просто заменяет старый HTML в контейнере. Обычно это происходит мгновенно и резко.

Чтобы добавить плавную анимацию, нам не нужно переписывать логику рендеринга. Нам нужно всего лишь «обернуть» момент изменения DOM в вызов document.startViewTransition.

Вот универсальный паттерн, который (важно!) не сломает сайт в большинстве случаев при простом DOM-обновлении:

function updateContent(newHTML) {
  const container = document.querySelector('#container');
View Transitions API: полное руководство по плавным переходам в браузере - 3 [4]

// 1. Проверяем поддержку (Progressive Enhancement)

  // Если браузер не знает про API, просто обновляем контент по-старому:

  if (!document.startViewTransition) {
    container.innerHTML = newHTML;
    return;
  }
View Transitions API: полное руководство по плавным переходам в браузере - 4 [4]

  // 2. Если поддержка есть — запускаем магию:

  document.startViewTransition(() => {
View Transitions API: полное руководство по плавным переходам в браузере - 5 [4]

    // Внутри этого колбэка мы делаем всё то же самое:

    // просто меняем DOM. Браузер сам поймёт, что изменилось.

container.innerHTML = newHTML;
  });
}
View Transitions API: полное руководство по плавным переходам в браузере - 6 [4]

Что здесь происходит? Мы говорим браузеру: «Запиши, как всё выглядит сейчас. Потом выполни мою функцию updateContent. А затем плавно преврати старую картинку в новую».

По ссылке [5] на демо доступен готовый рабочий пример View Transitions API, который включает HTML-структуру, CSS-оформление, JavaScript-логику:

View Transitions API: полное руководство по плавным переходам в браузере - 7

Управление процессом через промисы

startViewTransition возвращает объект с промисами, которые позволяют тонко контролировать жизненный цикл перехода. Это полезно, если вам нужно скоординировать JS-анимацию с переходом.

JavaScript

const transition = document.startViewTransition(() => updateDOM());
View Transitions API: полное руководство по плавным переходам в браузере - 8 [4]

// 1. DOM обновлён, но анимация ещё не началась:

await transition.updateCallbackDone;
View Transitions API: полное руководство по плавным переходам в браузере - 9 [4]

// 2. Псевдоэлементы созданы, анимация готова к старту:

await transition.ready;
View Transitions API: полное руководство по плавным переходам в браузере - 10 [4]

// 3. Анимация полностью завершена, псевдоэлементы удалены:

await transition.finished;
View Transitions API: полное руководство по плавным переходам в браузере - 11 [4]

Кастомизация анимаций через CSS

По умолчанию браузер делает простое перекрёстное затухание (cross-fade). Чтобы сделать красиво, нам понадобится CSS и свойство view-transition-name.

1. Связывание элементов.

Чтобы анимировать конкретный блок отдельно от остальной страницы, дайте ему уникальное имя:

CSS

card {
  view-transition-name: card-hero;
}
View Transitions API: полное руководство по плавным переходам в браузере - 12 [4]

2. Настройка анимации.

Теперь мы можем обратиться к псевдоэлементам этого блока и задать свои кейфреймы:

CSS

/* Старое состояние улетает */

::view-transition-old(card-hero) {
  animation: 300ms ease-out both fade-scale-out;
}
View Transitions API: полное руководство по плавным переходам в браузере - 13 [4]

/* Новое состояние прилетает */

::view-transition-new(card-hero) {
  animation: 300ms ease-in both fade-scale-in;
}

@keyframes fade-scale-out {
  to { opacity: 0; transform: scale(0.9); }
}

@keyframes fade-scale-in {
  from { opacity: 0; transform: scale(1.1); }
}
View Transitions API: полное руководство по плавным переходам в браузере - 14 [4]

По ссылке [6] доступен код примера, где карточка меняет текст с кастомной анимацией масштабирования и прозрачности:

View Transitions API: полное руководство по плавным переходам в браузере - 15

Shared elements: подходы и опасные ловушки

Это та самая киллер-фича: если на одной странице у картинки view-transition-name: hero, и на новой странице у (другой!) картинки тоже view-transition-name: hero, то браузер автоматически рассчитает их позиции и размеры, плавно трансформируя первую во вторую.

И вот тут главная ловушка: view-transition-name должен быть уникальным на странице в каждый момент времени. Если вы зададите всем карточкам в списке имя hero, то переход просто сломается.

Вот какое решение у этой ситуации может быть: назначайте имя динамически перед кликом.

JavaScript

function openProduct(id) {
  const cardImg = document.querySelector(`[data-id="${id}"] img`);
View Transitions API: полное руководство по плавным переходам в браузере - 16 [4]

 // 1. Временно даём имя кликнутому элементу:

  cardImg.style.viewTransitionName = 'hero';
  
  const transition = document.startViewTransition(() => {
    renderProductPage(id);
View Transitions API: полное руководство по плавным переходам в браузере - 17 [4]

  // На новой странице у большой картинки в CSS уже должно быть прописано view-transition-name: hero

});
View Transitions API: полное руководство по плавным переходам в браузере - 18 [4]

  // 2. Убираем имя после завершения, чтобы не было конфликтов:

  transition.finished.then(() => {
    cardImg.style.viewTransitionName = '';
  });
}
View Transitions API: полное руководство по плавным переходам в браузере - 19 [4]

Продвинутые сценарии

Асинхронные обновления и Suspense

View Transition API ожидает, что callback выполнится синхронно или вернёт промис. Браузер будет держать «замороженный» экран до завершения этого промиса.

JavaScript

document.startViewTransition(async () => {
  const data = await fetchData(); // Ждём сеть
  renderContent(data);            // Обновляем DOM
});
View Transitions API: полное руководство по плавным переходам в браузере - 20 [4]

Небольшой совет: не затягивайте ожидание, иначе пользователь подумает, что интерфейс завис.

Работа с фреймворками (React)

React обновляет DOM асинхронно и пакетами (batching). Чтобы View Transitions API сработал корректно, обновление DOM должно произойти внутри колбэка.

В React для этого используем flushSync, который заставляет React применить изменения немедленно:

JavaScript

import { flushSync } from 'react-dom';
document.startViewTransition(() => {
  flushSync(() => {
    setState(newState);
  });
});
View Transitions API: полное руководство по плавным переходам в браузере - 21 [4]

Note: В экспериментальных сборках React ведётся работа над нативной интеграцией, но в стабильный релиз этот API пока не вошёл. Поэтому сейчас рабочим решением для продакшена остаётся ручной вызов нативного document.startViewTransition в связке с flushSync.

Cross-document (MPA) переходы

С версии Chrome 126+ (и Safari 18+) можно анимировать переходы между разными HTML-страницами. Больше не нужно делать SPA, чтобы получить плавные переходы!

Достаточно добавить CSS на обеих страницах:

CSS

@view-transition {
  navigation: auto;
}
View Transitions API: полное руководство по плавным переходам в браузере - 22 [4]

Для мгновенной загрузки следующей страницы используйте Speculation Rules API (prerender):

HTML

<script type="speculationrules">
{ "prerender": [{ "source": "document", "where": { "selector": "a" } }] }
</script>
View Transitions API: полное руководство по плавным переходам в браузере - 23 [4]

Чеклист перед выходом в продакшен

API мощный, но при неправильном использовании легко сломать вёрстку или доступность. Проверьте себя перед релизом:

  • Обязательно проверяйте наличие document.startViewTransition.

  • Уважайте пользователей, у которых отключена анимация. Вот пример кода, который делает переходы мгновенными для тех, кто выбрал системную настройку prefers-reduced-motion:

CSS

@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) {
    animation-duration: 0.01ms !important;
    }
}
View Transitions API: полное руководство по плавным переходам в браузере - 24 [4]
  • Ориентируйтесь примерно на эту производительность:

    Длительность анимации не должна превышать 300-400 мс (это влияет на метрику INP).

    Обязательно должен быть протестирован LCP на мобильных устройствах.

  • Убедитесь, что нет дублей view-transition-name.

  • Проверьте отсутствие сдвигов контента и при проблемах с изображениями используйте object-fit: cover.

Итог

View Transitions API — это тот редкий случай, когда веб-стандарты догнали веб-приложения. Мы получили инструмент, который берёт на себя самую сложную математику анимаций (синхронизацию, позиционирование, композитинг) и оставляет нам чистое творчество.

Статус поддержки:

  • Chrome/Edge — полная поддержка (v111+).

  • Safari — поддержка появляется в Safari 18, на момент написания частично и с ограничениями.

  • Firefox — в активной разработке. API уже доступен в экспериментальных сборках (Nightly), но в стабильный релиз пока не вошёл.

С правильным фолбэком эту технологию можно и нужно использовать уже сегодня, чтобы делать веб чуть более приятным местом.

Автор: sergodeem

Источник [7]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/shared-elements/444716

Ссылки в тексте:

[1] Пол Льюис из Google представил концепцию FLIP: https://youtube.com/watch?v=RCFQu0hK6bU&embeds_referring_euri=https%3A%2F%2Faerotwist.com%2F&source_ve_path=OTY3MTQ

[2] в Chrome 111 появился View Transitions API: https://habr.com/ru/articles/721292/

[3] Джейк Арчибальд на Chrome Dev Summit: https://developer.chrome.com/docs/web-platform/view-transitions?hl=ru#:~:text=Transitions%20created%20with%20the%20View,same%20building%20blocks%20and%20principles:

[4] Image: https://sourcecraft.dev/

[5] ссылке: https://codepen.io/xdkbnvns-the-sasster/pen/pvbrexN

[6] ссылке: https://codepen.io/xdkbnvns-the-sasster/pen/GgqvWzb

[7] Источник: https://habr.com/ru/articles/996498/?utm_source=habrahabr&utm_medium=rss&utm_campaign=996498