Клавиша / esc

@view-transition

Создаём плавные анимации при переходе между страницами.

Время чтения: меньше 5 мин

Кратко

Скопировано

@view-transition — это CSS-директива для создания плавных анимаций перехода между страницами сайта.

Пример

Скопировано

Настроить переход можно в одно правило. Браузер применит дефолтную cross-fade анимацию:

        
          
          @view-transition {  navigation: auto;}
          @view-transition {
  navigation: auto;
}

        
        
          
        
      

Если нужно закастомить, можно добавить свою:

        
          
          ::view-transition-old(root) {  animation: 0.3s ease-in-out both slideOut;}::view-transition-new(root) {  animation: 0.3s ease-in-out both zoomIn;}
          ::view-transition-old(root) {
  animation: 0.3s ease-in-out both slideOut;
}

::view-transition-new(root) {
  animation: 0.3s ease-in-out both zoomIn;
}

        
        
          
        
      

Вот что получится:

Открыть демо в новой вкладке

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

  • Главная появляется через zoomIn, уходит через zoomOut.
  • Страница подробностей появляется через slideIn, уходит через slideOut.

Тонкость в том, что мы можем описать уходящую анимацию только в новой странице. Поэтому уходящая анимация zoomOut описана на странице подробностей, а slideOut — на главной.

При должной аккуратности этот паттерн можно легко масштабировать. Он отлично подходит для создания визуальной иерархии между переходами.

Как пишется

Скопировано

Базовый синтаксис:

        
          
          @view-transition {  navigation: auto;}
          @view-transition {
  navigation: auto;
}

        
        
          
        
      

Свойство navigation внутри директивы принимает одно из двух значений:

  • none — значение по умолчанию, плавные переходы отключены.
  • auto — браузер применяет стандартную анимацию перехода.

Вот как добавить свою анимацию перехода:

        
          
          ::view-transition-old(root) {  animation: 0.3s ease-in-out both slideOut;}::view-transition-new(root) {  animation: 0.3s ease-in-out both zoomIn;}
          ::view-transition-old(root) {
  animation: 0.3s ease-in-out both slideOut;
}

::view-transition-new(root) {
  animation: 0.3s ease-in-out both zoomIn;
}

        
        
          
        
      

Как понять

Скопировано

@view-transition работает как контейнер для определения правил перехода между страницами. При навигации браузер автоматически создаёт анимацию перехода при указанном @view-transition.

Обе страницы должны находиться на одном origin. origin — это комбинация протокола, домена и порта (если он указан). Например, doka.guide — это домен, а https://doka.guideorigin.

Опциональная анимация

Скопировано

По умолчанию директива @view-transition со значением auto применяется всегда. При желании её можно ограничить с помощью условных директив.

Например, можно пощадить пользователей, которые предпочитают минимальное количество анимаций:

        
          
          @media screen and (prefers-reduced-motion: no-preference) {  @view-transition {    navigation: auto;  }}
          @media screen and (prefers-reduced-motion: no-preference) {
  @view-transition {
    navigation: auto;
  }
}

        
        
          
        
      

Или включить плавные переходы только для определённых размеров экрана:

        
          
          @media screen and (width > 70em) {  @view-transition {    navigation: auto;  }}
          @media screen and (width > 70em) {
  @view-transition {
    navigation: auto;
  }
}

        
        
          
        
      

Гранулярная анимация

Скопировано

Помимо анимации всей страницы, можно независимо анимировать отдельные элементы. Для этого нужно:

  1. Задать уникальное имя перехода с помощью свойства view-transition-name.
  2. Задать отдельную анимацию для перехода.
        
          
          header {  view-transition-name: header;}::view-transition-old(header) {  animation: 0.3s ease-in-out both fadeOut;}::view-transition-new(header) {  animation: 0.3s ease-in-out both fadeIn;}
          header {
  view-transition-name: header;
}

::view-transition-old(header) {
  animation: 0.3s ease-in-out both fadeOut;
}

::view-transition-new(header) {
  animation: 0.3s ease-in-out both fadeIn;
}

        
        
          
        
      

Теперь <header> будет анимироваться независимо от основного перехода страницы. Ниже пример.

Открыть демо в новой вкладке
Поддержка в браузерах:
  • Chrome 126, поддерживается
  • Edge 126, поддерживается
  • Firefox, не поддерживается
  • Safari 18.2, поддерживается
О Baseline

На практике

Скопировано

Антон Субботин советует

Скопировано

@view-transition — это мощный и в то же время простой инструмент. Подключается всего одной директивой и выступает прекрасным примером принципа Progressive enhancement: если браузер не поддерживает директиву, то ничего не развалится, сайт останется функциональным.

Пара советов по использованию:

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