Переходы между элементами группы

Когда элементы добавляются в список, удаляются из него или переупорядочиваются, переходы могут помочь пользователям сохранить контекст. Переходы между представлениями позволяют переходить между двумя состояниями элемента, присваивая элементу уникальный view-transition-name. Если у нескольких элементов на странице одинаковое поведение перехода, view-transition-class позволяет определить эту логику один раз в CSS, а не повторять ее для каждого уникального view-transition-name. Это позволяет поддерживать таблицы стилей и обеспечивает согласованность анимации для группы элементов.

Реализация

  1. Как назначить уникальные названия и общий курс

    Каждый элемент, который необходимо отслеживать отдельно во время перехода, должен иметь уникальный view-transition-name.

    <!-- Mandatory: Each element must have a unique view-transition-name -->
    <li style="view-transition-name: item-1" class="item">Item 1</li>
    <li style="view-transition-name: item-2" class="item">Item 2</li>
    

    Чтобы применить общие стили, также назначьте view-transition-class.

    .item {
      view-transition-class: list-item;
    }
    
  2. Определите логику перехода

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

    /* Targets any view transition group that has the 'list-item' class */
    ::view-transition-group(.list-item) {
      animation-duration: 0.5s;
      animation-timing-function: ease-in-out;
    }
    
    /* Handle accessibility by respecting motion preferences */
    @media (prefers-reduced-motion: reduce) {
      /* Disable all group transitions, including the default `root` group. */
      ::view-transition-group(*),
      ::view-transition-old(*),
      ::view-transition-new(*) {
        animation: none !important;
      }
    }
    
  3. Как настроить анимацию при появлении и исчезновении (необязательно)

    Используйте селектор :only-child, чтобы добавить определенные переходы к добавляемым или удаляемым элементам. Псевдоэлементы ::view-transition-new() и ::view-transition-old() являются дочерними элементами псевдоэлемента ::view-transition-image-pair(), поэтому мы можем определить, является ли он добавленным или удаленным элементом, если он является единственным дочерним элементом.

    /* A `::view-transition-new()` element is the only child if it wasn't present before the view transition, so it is an added element. */
    ::view-transition-new(.list-item):only-child {
      animation-name: slide-in;
      /* Specify an animation duration if you want something different than the UA default of 0.5s */
      animation-duration: 1s;
    }
    /* A `::view-transition-old()` element is the only child if it isn't present after the view transition, so it is a removed element. */
    ::view-transition-old(.list-item):only-child {
      animation-name: slide-out;
      /* Specify an animation duration if you want something different than the UA default of 0.5s */
      animation-duration: 1s;
    }
    
    @keyframes slide-in {
      from {
        translate: -100vw 0;
      }
    }
    @keyframes slide-out {
      to {
        translate: -100vw 0;
      }
    }
    
  4. Как запустить переход

    Оберните обновление DOM в document.startViewTransition(). Браузер зафиксирует старое состояние, выполнит обновление, а затем анимирует новое состояние.

    function updateList(newData) {
      document.startViewTransition(() => {
        // All DOM changes inside this callback will be transitioned
        render(newData);
      });
    }
    
  5. Поддерживайте интерактивность элементов, не участвующих в переходе

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

::view-transition {
  /* Non-transitioned elements below the view transitions remain interactive */
  pointer-events: none;
}

Кроме того, по умолчанию элемент :root имеет переход представления с именем root, который включает переходы по умолчанию на всю страницу. Если в корневом элементе нет изменений, это будет переход между двумя идентичными снимками, которые не являются интерактивными. Поскольку мы переносим только определенные элементы, а не весь экран, мы можем отключить переход root.

:root {
  /* Disable the root transition because we are only transitioning specific elements. */
  view-transition-name: none;
}

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

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

if (document.startViewTransition) {
  document.startViewTransition(() => updateDOM());
} else {
  // Fallback: Perform the update without animation
  updateDOM();
}

Браузеры, которые не распознают view-transition-class или селектор класса ::view-transition-group(), просто проигнорируют эти правила, и анимация не будет применена.