Начните работу с анимацией, управляемой прокруткой, в CSS.Начните работу с анимацией, управляемой прокруткой, в CSS.

1. Прежде чем начать

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

В Chrome 115 появилась поддержка набора классов JavaScript и свойств CSS, позволяющих легко создавать декларативные анимации, управляемые прокруткой. Эти новые API работают совместно с существующими API веб-анимаций и CSS-анимаций.

В этом практическом занятии вы научитесь создавать анимации, управляемые прокруткой, с помощью CSS. Пройдя это занятие, вы познакомитесь со многими новыми свойствами CSS, появившимися благодаря этой замечательной функции, такими как scroll-timeline , view-timeline , animation-timeline и animation-range .

Что вы узнаете

  • Как создать эффект параллаксного фона с помощью прокручиваемой временной шкалы в CSS.
  • Как создать индикатор выполнения с прокручиваемой временной шкалой в CSS.
  • Как создать эффект появления изображения с помощью элемента View Timeline в CSS.
  • Как задать различные диапазоны значений на временной шкале представления в CSS.

Что вам понадобится

Одна из следующих комбинаций устройств:

  • Для работы требуется последняя версия Chrome (115 или более поздняя) на ChromeOS, macOS или Windows с включенным флагом "Experimental Web Platform Features".
  • Базовое понимание HTML
  • Фундаментальное понимание CSS, в частности анимации в CSS.

2. Настройка

Все необходимое для этого проекта доступно в репозитории GitHub. Для начала клонируйте код и откройте его в вашей любимой среде разработки.

  1. Откройте новую вкладку браузера и перейдите по ссылке https://github.com/googlechromelabs/io23-scroll-driven-animations-codelab .
  2. Клонируйте репозиторий.
  3. Откройте код в предпочитаемой вами IDE.
  4. Для установки зависимостей выполните npm install .
  5. Запустите команду npm start и перейдите по адресу http://localhost:3000/ .
  6. В качестве альтернативы, если у вас не установлен npm, откройте файл src/index.html в Chrome.

3. Изучите временные рамки анимации.

По умолчанию анимация, прикрепленная к элементу, воспроизводится на временной шкале документа. Это означает, что при загрузке страницы анимация отсчитывает время вперед. Это временная шкала анимации по умолчанию, и до настоящего момента это была единственная доступная вам временная шкала анимации.

Благодаря анимации, управляемой прокруткой, вы получаете доступ к двум новым типам временных шкал:

  • Хронология прогресса прокрутки
  • Просмотреть хронологию прогресса

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

Хронология прогресса прокрутки

Шкала прогресса прокрутки — это шкала анимации, которая связана с прогрессом в положении прокрутки контейнера прокрутки (также называемого областью прокрутки или скроллером) вдоль определенной оси. Она преобразует положение в диапазоне прокрутки в процент прогресса вдоль временной шкалы.

Начальная позиция прокрутки соответствует 0% прогресса, а конечная — 100% прогресса. На приведенной ниже визуализации обратите внимание, что прогресс увеличивается от 0% до 100% по мере прокрутки вниз.

Просмотреть хронологию прогресса

Этот тип временной шкалы связан с относительным продвижением определенного элемента внутри контейнера прокрутки. Как и в случае с временной шкалой прогресса прокрутки, отслеживается смещение прокрутки в скроллере. В отличие от временной шкалы прогресса прокрутки, именно относительное положение объекта внутри скроллера определяет прогресс. Это сравнимо с IntersectionObserver , который отслеживает, насколько элемент виден в скроллере. Если элемент не виден в скроллере, он не пересекается. Если он виден внутри скроллера — даже в самой маленькой части — он пересекается.

Отображение прогресса начинается с момента, когда объект начинает пересекать полосу прокрутки, и заканчивается, когда объект перестает пересекать полосу прокрутки. На следующей визуализации обратите внимание, что отсчет прогресса начинается с 0%, когда объект входит в контейнер прокрутки, и достигает 100% к моменту, когда он покидает контейнер прокрутки.

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

Также можно привязать его к определенной части временной шкалы прогресса просмотра, указав диапазон, к которому он должен быть привязан. Например, это может быть только момент, когда объект входит в область прокрутки. На следующей визуализации прогресс начинает отсчет с 0%, когда объект входит в контейнер прокрутки, но достигает 100% уже с момента полного пересечения с ним.

Возможные диапазоны временной шкалы просмотра, на которые вы можете нацелиться, это: cover , contain , entry , exit , entry-crossing и exit-crossing . Эти диапазоны объясняются далее в этом практическом руководстве, но если вы не хотите ждать, воспользуйтесь инструментом, расположенным по адресу https://goo.gle/view-timeline-range-tool, чтобы увидеть, что представляет собой каждый диапазон.

4. Создайте эффект параллаксного фона.

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

Для реализации этого необходимо выполнить два шага:

  1. Создайте анимацию, которая изменяет положение фонового изображения.
  2. Свяжите анимацию с процессом прокрутки документа.

Создайте анимацию

  1. Для создания анимации используйте стандартный набор ключевых кадров. В нём переместите положение фона от 0% по вертикали до 100%:

src/styles.css

@keyframes move-background {
  from {
    background-position: 50% 0%;
  }
  to {
    background-position: 50% 100%;
  }
}
  1. Теперь прикрепите эти ключевые кадры к элементу body:

src/styles.css

body {
  animation: 1s linear move-background;
}

С помощью этого кода к элементу body добавляется анимация move-background . Свойство animation-duration устанавливается на одну секунду, и используется linear сглаживание.

Самый простой способ создать временную шкалу прогресса прокрутки — использовать функцию scroll() . Она создаст анонимную временную шкалу прогресса прокрутки, значение которой можно задать в свойстве animation-timeline .

Функция scroll() принимает аргументы <scroller> и <axis> .

Допустимые значения для аргумента <scroller> следующие:

  • nearest . Использует ближайший родительский контейнер прокрутки (по умолчанию).
  • root . Использует область просмотра документа в качестве контейнера прокрутки.
  • self . Использует сам элемент в качестве контейнера прокрутки.

Допустимые значения для аргумента <axis> следующие:

  • block . Использует скорость продвижения вдоль оси блока контейнера прокрутки (по умолчанию).
  • inline . Использует показатель прогресса вдоль оси прокрутки контейнера.
  • y . Использует показатель прогресса вдоль оси Y контейнера прокрутки.
  • x . Использует показатель прогресса вдоль оси x контейнера прокрутки.

Для привязки анимации к корневому скроллеру по оси блока значения, передаваемые в функцию scroll() — это root и block . В совокупности это значение будет scroll(root block) .

  • Установите значение свойства animation-timeline для элемента body в качестве параметра scroll(root block) .
  • Кроме того, поскольку animation-duration выраженная в секундах, не имеет смысла, установите значение auto . Если вы не укажете animation-duration , по умолчанию будет установлено значение auto .

src/styles.css

body {
  animation: linear move-background;
  animation-duration: auto;
  animation-timeline: scroll(root block);
}

Поскольку корневой скроллер также является ближайшим родительским скроллером для элемента body, вы также можете использовать значение nearest :

src/styles.css

body {
  animation: linear move-background;
  animation-duration: auto;
  animation-timeline: scroll(nearest block);
}

Поскольку nearest и block являются значениями по умолчанию, вы можете даже их опустить. В этом случае код можно упростить до следующего вида:

src/styles.css

body {
  animation: linear move-background;
  animation-duration: auto;
  animation-timeline: scroll();
}

Проверьте внесенные изменения.

Если всё прошло успешно, у вас должно получиться следующее:

В противном случае, посмотрите ветку кода solution-step-1 .

5. Создайте индикатор выполнения для галереи изображений.

На странице находится горизонтальная карусель, для отображения которой необходима полоса прогресса.

Разметка для карусели выглядит следующим образом:

src/index.html

<div class="gallery">
  <div class="gallery__scrollcontainer" style="--num-images: 3;">
    <div class="gallery__progress"></div>
    <div class="gallery__entry">
      ...
    </div>
    <div class="gallery__entry">
      ...
    </div>
    <div class="gallery__entry">
      ...
    </div>
  </div>
</div>

Ключевые кадры для индикатора выполнения уже созданы и выглядят следующим образом:

src/styles.css

@keyframes adjust-progress {
  from {
    transform: scaleX(calc(1 / var(--num-images)));
  }
  to {
    transform: scaleX(1);
  }
}

Эту анимацию необходимо прикрепить к элементу ` gallery__progress с помощью временной шкалы прогресса прокрутки. Как показано на предыдущем шаге, этого можно добиться, создав анонимную временную шкалу прогресса прокрутки с помощью функции scroll() :

src/styles.css

.gallery__progress {
  animation: linear adjust-progress;
  animation-duration: auto;
  animation-timeline: scroll(nearest inline);
}

Хотя этот фрагмент кода может показаться рабочим, на самом деле это не так из-за особенностей автоматического поиска контейнера прокрутки с помощью метода ` nearest . При поиске ближайшего элемента прокрутки учитываются только те элементы, которые могут повлиять на его положение. Поскольку .gallery__progress имеет абсолютное позиционирование, первым родительским элементом, определяющим его положение, является элемент ` .gallery , поскольку к нему применено position: relative . Это означает, что элемент ` .gallery__scrollcontainer — именно тот элемент прокрутки, который необходимо найти, — вообще не учитывается при этом автоматическом поиске.

Чтобы обойти эту проблему, создайте именованную временную шкалу прогресса прокрутки для элемента .gallery__scrollcontainer и свяжите с ней элемент .gallery__progress , используя это имя.

Чтобы создать именованную временную шкалу прогресса прокрутки для элемента, установите свойство CSS scroll-timeline-name контейнера прокрутки на любое желаемое значение. Значение должно начинаться с -- .

Поскольку галерея прокручивается по горизонтали, вам также необходимо установить свойство scroll-timeline-axis . Допустимые значения совпадают с аргументом <axis> функции scroll() .

Наконец, чтобы связать анимацию с временной шкалой прогресса прокрутки, установите свойство animation-timeline элемента, который необходимо анимировать, на то же значение, что и идентификатор, используемый для scroll-timeline-name .

  • Измените файл styles.css , добавив в него следующее:

src/styles.css

.gallery__scrollcontainer {
  /* Create the gallery-is-scrolling timeline */
  scroll-timeline-name: --gallery-is-scrolling;
  scroll-timeline-axis: inline;
}

.gallery__progress {
  animation: linear adjust-progress;
  animation-duration: auto;
  /* Set gallery-is-scrolling as the timeline */
  animation-timeline: --gallery-is-scrolling;
}

Проверьте внесенные изменения.

Если всё прошло успешно, у вас должно получиться следующее:

В противном случае, посмотрите ветку кода solution-step-2 .

6. Анимируйте изображения в галерее при их появлении и исчезновении из области прокрутки.

Настройте анонимный просмотр графика выполнения работ.

Интересный эффект — плавное появление изображений в галерее по мере их появления. Для этого можно использовать функцию «Просмотр временной шкалы».

Для создания временной шкалы прогресса можно использовать функцию view() . Ее принимаемые аргументы: <axis> и <view-timeline-inset> .

  • Параметр <axis> аналогичен параметру на временной шкале прогресса прокрутки и определяет, какую ось отслеживать.
  • С помощью <view-timeline-inset> ` можно указать смещение (положительное или отрицательное), чтобы корректировать границы элемента в зависимости от того, находится ли он в поле зрения или нет.
  • Ключевые кадры уже созданы, поэтому вам нужно только их прикрепить. Для этого создайте шкалу прогресса просмотра для каждого элемента .gallery__entry .

src/styles.css

@keyframes animate-in {
  from {
    opacity: 0;
    clip-path: inset(50% 0% 50% 0%);
  }
  to {
    opacity: 1;
    clip-path: inset(0% 0% 0% 0%);
  }
}

.gallery__entry {
  animation: linear animate-in;
  animation-duration: auto;
  animation-timeline: view(inline);
}

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

Если сохранить CSS-код и загрузить страницу, вы увидите, как элементы плавно появляются, но что-то кажется не так. Их прозрачность равна 0 , когда они полностью исчезают из поля зрения, и достигает 1 только после полного исчезновения.

Это связано с тем, что диапазон по умолчанию для отображения временной шкалы хода выполнения — полный диапазон. Он называется диапазоном cover .

  1. Чтобы ограничить область действия анимации только определенным диапазоном entry объекта, используйте свойство CSS ` animation-range , чтобы установить ограничение на время запуска анимации.

src/styles.css

.gallery__entry {
  animation: linear fade-in;
  animation-duration: auto;
  animation-timeline: view(inline);
  animation-range: entry 0% entry 100%;
}

Теперь анимация начинается с entry 0% (объект вот-вот войдет в полосу прокрутки) и entry 100% (объект полностью вошел в полосу прокрутки).

Возможные диапазоны временной шкалы просмотра следующие:

  • cover . Отображает полный диапазон временной шкалы прогресса просмотра.
  • entry . Представляет собой диапазон, в течение которого основной блок входит в зону видимости индикатора выполнения.
  • exit . Представляет собой диапазон, в течение которого основной блок выходит за пределы видимой области отображения прогресса.
  • entry-crossing . Обозначает диапазон, в течение которого основной прямоугольник пересекает край конечной границы.
  • exit-crossing . Обозначает диапазон, в течение которого основной прямоугольник пересекает начальную границу.
  • contain . Представляет диапазон, в течение которого основной блок либо полностью содержится в пределах области видимости индикатора выполнения, либо полностью закрывает ее. Это зависит от того, выше или ниже объект, чем полоса прокрутки.

Воспользуйтесь инструментом, расположенным по адресу https://goo.gle/view-timeline-range-tool, чтобы увидеть, что представляет собой каждый диапазон и как проценты влияют на начальную и конечную позиции.

  1. Поскольку начальный и конечный диапазоны здесь одинаковы, и используются смещения по умолчанию, упростите имя animation-range до одного имени диапазона анимации:

src/styles.css

.gallery__entry {
  animation: linear animate-in;
  animation-duration: auto;
  animation-timeline: view(inline);
  animation-range: entry;
}
  • Чтобы изображения плавно исчезали при выходе из зоны прокрутки, можно использовать тот же подход, что и для анимации появления, но выбрать другой диапазон.

src/styles.css

@keyframes animate-out {
  from {
    opacity: 1;
    clip-path: inset(0% 0% 0% 0%);
  }
  to {
    opacity: 0;
    clip-path: inset(50% 0% 50% 0%);
  }
}

.gallery__entry {
  animation: linear animate-in, linear animate-out;
  animation-duration: auto;
  animation-timeline: view(inline);
  animation-range: entry, exit;
}

Ключевые кадры animate-in будут применены к диапазону entry , а ключевые кадры animate-out к диапазону exit .

Проверьте внесенные изменения.

Если всё прошло успешно, у вас должно получиться следующее:

В противном случае, посмотрите ветку кода solution-step-3 .

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

Аргументы в пользу одного набора ключевых кадров

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

Форма ключевых кадров выглядит следующим образом:

@keyframes keyframes-name {
  range-name range-offset {
    ...
  }
  range-name range-offset {
    ...
  }
}
  1. Объедините ключевые кадры появления и исчезновения следующим образом:

src/styles.css

@keyframes animate-in-and-out {
  entry 0% {
    opacity: 0;
    clip-path: inset(50% 0% 50% 0%);
  }
  entry 90% {
    opacity: 1;
    clip-path: inset(0% 0% 0% 0%);
  }

  exit 10% {
    opacity: 1;
    clip-path: inset(0% 0% 0% 0%);
  }
  exit 100% {
    opacity: 0;
    clip-path: inset(50% 0% 50% 0%);
  }
}
  1. Если информация о диапазоне присутствует в ключевых кадрах, вам больше не нужно указывать animation-range отдельно. Прикрепите ключевые кадры в качестве свойства animation .

src/styles.css

.gallery__entry {
  animation: linear animate-in-and-out both;
  animation-duration: auto;
  animation-timeline: view(inline);
}

Проверьте внесенные изменения.

Если все прошло успешно, вы должны получить тот же результат, что и на предыдущем шаге. В противном случае, проверьте ветку кода solution-step-4 .

8. Поздравляем!

Вы завершили этот практический урок и теперь знаете, как создавать временные шкалы прогресса прокрутки и отображения в CSS!

Узнать больше

Ресурсы: