Переходы при навигации по направлениям

В одностраничных приложениях (SPA) навигация имитируется за счет замены контента страницы без перехода на новую страницу. По умолчанию контент просто заменяется без каких-либо переходов. Направленные переходы могут визуально усилить пространственную связь между представлениями.

Если новый контент появляется с той стороны, в которую движется пользователь, у него формируется мысленная карта структуры приложения. Например, на сайте с товарами переход вправо может означать "вперед", а влево – "назад". В слайд-шоу переход вверх и вниз может показывать следующий и предыдущий слайды.

Руководство по настройке

  1. Определять направление навигации. Определяйте, перемещается ли пользователь вперед или назад в приложении. Способ определения направления зависит от вашего сценария использования.
  2. Запуск перехода с типами. Передайте направление в массиве types в document.startViewTransition(), чтобы классифицировать переход.
  3. Определите направленные анимации с помощью CSS. Используйте псевдокласс :active-view-transition-type(), чтобы применять определенные анимации в зависимости от типа навигации.

Определение ключевых кадров

Задайте анимацию скольжения в каждом направлении. Для достижения наилучшей производительности анимируйте изменения положения с помощью свойства transform или отдельных свойств преобразования: scale, rotate и translate. Свойство opacity также обычно работает быстро, но не анимируйте другие свойства CSS, не убедившись, что они не запускают макет или отрисовку.

/* Slide an element out to the left */
@keyframes slide-to-left {
  /* Mandatory: animate `transform` instead of inset properties for better performance. */
  to { transform: translateX(-100%); }
}

/* Slide an element in from the right */
@keyframes slide-from-right {
  from { transform: translateX(100%); }
}

/* Slide an element out to the right */
@keyframes slide-to-right {
  to { transform: translateX(100%); }
}

/* Slide an element in from the left */
@keyframes slide-from-left {
  from { transform: translateX(-100%); }
}

Как настроить общие параметры анимации

Используйте селектор ::view-transition-group(root), чтобы применить настройки анимации, которые будут использоваться для всех переходов.

::view-transition-group(root){
  animation: 0.4s ease-in-out both;
}

Применение направленной анимации

Используйте псевдокласс active-view-transition-type, чтобы настроить таргетинг на представления перехода, когда активен тип "вперед" или "назад".

/* MANDATORY: Apply forward animations when the 'forward' type is active */
html:active-view-transition-type(forward)::view-transition-old(root) {
  animation-name: slide-to-left;
}
html:active-view-transition-type(forward)::view-transition-new(root) {
  animation-name: slide-from-right;
}

/* MANDATORY: Apply backward animations when the 'backward' type is active */
html:active-view-transition-type(backward)::view-transition-old(root) {
  animation-name: slide-to-right;
}
html:active-view-transition-type(backward)::view-transition-new(root) {
  animation-name: slide-from-left;
}

Как запустить переход

При навигации передайте нужный тип в метод startViewTransition.

const transitionType = yourTransitionTypeLogic();
const updateDOM = yourUpdateDOMLogic();

document.startViewTransition({
  update: updateDOM,
  types: [transitionType] // Matches the CSS :active-view-transition-type() selectors
});

Специальные возможности

Всегда учитывайте предпочтения пользователей в отношении уменьшения движения, отключая или упрощая анимацию.

@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(root) {
    animation: none !important;
  }
}

Резервные стратегии

View Transitions API – это прогрессивное улучшение. В неподдерживаемых браузерах document.startViewTransition будет undefined. Вам нужно обернуть логику навигации в проверку обнаружения функций, чтобы обновление DOM по-прежнему происходило немедленно без анимации, как показано в этой вспомогательной функции.

/**
 * Navigates to a new view with a directional transition.
 * @param {Function} updateDOM - Callback to update the DOM state.
 * @param {string} direction - Either 'forward' or 'backward'.
 */
function navigate(updateDOM, direction) {
  // Feature detect for browsers that do not support View Transitions
  if (!document.startViewTransition) {
    updateDOM();
    return;
  }

  // Start transition with the specific navigation type
  document.startViewTransition({
    update: updateDOM,
    types: [direction] // Matches the CSS :active-view-transition-type() selectors
  });
}