Реализация состояния пользовательского интерфейса с поддержкой прокрутки с помощью CSS
Интерактивные функции пользовательского интерфейса, такие как состояние пользовательского интерфейса с поддержкой прокрутки, могут улучшить взаимодействие с пользователем веб-сайта, но часто создают проблемы с оптимизацией производительности. Во многом это связано с тем, что большинство функций интерактивного пользовательского интерфейса реализованы с использованием JavaScript.
Решения, использующие только CSS, могут снизить рабочую нагрузку на конвейер рендеринга по сравнению с JavaScript, который работает в основном потоке. Однако существуют ограничения на то, чего можно достичь исключительно с помощью CSS.
В этой статье мы рассмотрим концепцию состояния пользовательского интерфейса с поддержкой прокрутки и обсудим, как оно может помочь найти баланс между уровнем интерактивности и производительностью системы. Мы также рассмотрим методы реализации этой функции, используя только CSS.
Предварительные условия
Чтобы следовать этому руководству, у вас должно быть:
- Базовые знания CSS
- Знакомство с JavaScript
Что такое состояние с поддержкой прокрутки?
Состояние пользовательского интерфейса с поддержкой прокрутки позволяет разработчикам создавать в веб-интерфейсах интерактивность, подобную встроенной. Это популярный подход для улучшения пользовательского опыта веб-сайта.
«Состояние прокрутки» может показаться непонятным термином, но это всего лишь причудливый способ сказать «UI, управляемый прокруткой» — это UX-шаблон, который динамически и адаптивно реагирует на действия пользователя по прокрутке на веб-странице.
Вот пример, демонстрирующий, как выглядит и ведет себя пользовательский интерфейс с поддержкой прокрутки:
Этот шаблон UX часто используется в сочетании с API-интерфейсами JavaScript, такими как API Intersection Observer, или сторонними пакетами для мониторинга, расчета и хранения состояния хода и положения прокрутки пользователя. Эта позиция затем может активировать анимацию или стили CSS, которые изменяют внешний вид, поведение или видимость элементов или компонентов на веб-странице.
Дизайн пользовательского интерфейса, управляемый прокруткой, может быть таким же простым, как привязка к прокрутке, фиксированное позиционирование или даже эффект параллакса, созданный исключительно с помощью CSS. Они также могут быть более сложными. Благодаря недавним дополнениям к спецификации CSS-анимации, управляемой прокруткой, теперь можно добиться тех же результатов, что и при сложных анимациях, созданных с помощью JavaScript, используя только CSS.
Реализация анимации с поддержкой прокрутки с помощью CSS
Пользовательский интерфейс с поддержкой прокрутки может варьироваться от простого эффекта привязки прокрутки до элемента, который анимируется, когда пользователь прокручивает его в поле зрения или когда пользователь прокручивает страницу вперед или назад в ответ. Есть несколько способов реализовать этот тип UX-шаблона.
Простая привязка к прокрутке — это наиболее распространенный тип пользовательского интерфейса с поддержкой прокрутки. Реализовать этот эффект так же просто, как добавить в контейнер однострочное свойство Scroll-Snap-type: y или Position: фиксированное, чтобы получить такой результат:
Этот тип пользовательского интерфейса с поддержкой прокрутки прост в реализации, но вы можете сделать гораздо больше, помимо нашего базового примера. Для более полного понимания того, как работают эти свойства и как их использовать, ознакомьтесь со статьями «Как стилизовать точки привязки прокрутки с помощью CSS» и «Создать собственную липкую панель навигации с помощью CSS».
Последний пример — не простой случай добавления свойства CSS в контейнер; для этого требуется вычислить расстояние прокрутки пользователем веб-страницы и определить, когда элемент появляется в поле зрения. CSS не поддерживает такую функциональность, поэтому анимация, управляемая прокруткой, с помощью CSS — по сути невозможная задача — или была таковой на момент написания статьи.
Новый набор API, которые работают совместно с API веб-анимации (WAAPI) и API анимации CSS, недавно был представлен в спецификации CSS-анимаций, управляемых прокруткой, чтобы облегчить реализацию декларативной анимации, управляемой прокруткой, с использованием только CSS. Эти API являются дополнением к списку значений свойств временной шкалы анимации, которые предоставляют новый и доступный способ управления ходом анимации CSS:
- Прокрутить шкалу прогресса
- Посмотреть график прогресса
Чтобы понять, как работают эти временные шкалы, давайте сначала посмотрим, что собой представляет временная шкала анимации.
Понимание свойства CSS-анимации-временной шкалы
Свойство CSS animation-timeline
используется для указания временной шкалы, которая управляет ходом анимации CSS. До появления временной шкалы прокрутки и просмотра прогресса у нас был доступ только к временной шкале документа по умолчанию.
Временная шкала документа была нестабильной, в ней не было возможностей настройки, и она постоянно менялась с момента начальной загрузки веб-страницы. Анимация веб-страницы автоматически запускается при загрузке страницы и продолжается в течение указанной продолжительности анимации. До того, как появилась возможность прокручивать и просматривать временные шкалы прогресса, не было гибкости для управления этим поведением.
Свойство анимации-timeline принимает любое из следующих значений: Scroll()
, view()
или auto
и назначается элементу, имеющему предустановку анимации. Например, чтобы повернуть элемент окна, когда пользователь прокручивает веб-страницу вверх или вниз, перед добавлением свойства animate-timeline
и определенного значения необходимо иметь предустановку анимации, подобную следующей:
#box {
animation-name: box;
animation-direction: alternate;
/* animation timeline with any of the accepted values */
}
@keyframes box {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
Это приведет к тому, что окно будет анимироваться, как и ожидалось, но вместо временной шкалы документа по умолчанию будет использоваться указанная временная шкала:
Прокрутить шкалу прогресса
Временная шкала прогресса прокрутки работает на основе положения прокрутки прокручиваемого элемента, который может называться портом прокрутки, скроллером или источником. Поскольку временная шкала привязана к контейнеру анимационного элемента, ее синхронизация изменяется только тогда, когда изменяется положение прокрутки контейнера.
Позиция прокрутки контейнера указывается в процентах: начальная позиция прокрутки представлена как 0%
, а конечная позиция прокрутки — 100%
. В этом отличие от временной шкалы документа по умолчанию, которая продолжает развиваться либо в течение указанного периода времени, либо в течение времени, пока веб-страница остается открытой (если продолжительность не указана).
Есть два способа определить временную шкалу прокрутки:
- Анонимный метод
- Именованный метод
Временная шкала анонимной прокрутки
Анонимный метод — это метод по умолчанию и самый быстрый способ определить временную шкалу прокрутки. Если вы используете функцию scroll()
и назначаете ее в качестве значения свойства animation-timeline
, временная шкала прогресса прокрутки выберет ближайшего предка скроллера и будет использовать его временную шкалу:
animation-timeline: scroll();
Функция scroll()
принимает два необязательных аргумента: <scroll>
и <axis>
. Аргумент <scroller>
используется для ссылки на источник (т. е. прокручиваемый элемент или контейнер) и его позицию прокрутки, которая будет управлять продвижением временной шкалы. Вот его принятые значения:
- nearest: выбирает ближайшего прокручиваемого предка текущего элемента.
- root: выбирает корневой элемент документа, например элемент <html>.
- self: выбирает сам текущий элемент, если он прокручивается.
Аргумент <axis>
используется для указания направления полосы прокрутки, которая будет использоваться для предоставления временной шкалы. Вот его принятые значения:
- block: использует меру прогресса вдоль оси блока контейнера прокрутки.
- inline: использует меру прогресса вдоль встроенной оси контейнера прокрутки.
- y: использует меру прогресса по вертикальной оси контейнера прокрутки.
- x: использует меру прогресса по горизонтальной оси контейнера прокрутки.
Значение по умолчанию функции scroll()
использует ближайшие значения осей прокрутки и блока:
animation-timeline: scroll(nearest block);
Приведенный выше код привяжет анимацию к корневому скроллеру на оси блока.
Временную шкалу прогресса прокрутки можно использовать для различных проектов с поддержкой прокрутки, но наиболее практичным вариантом использования является индикатор прогресса чтения. Это легко создать, используя анонимную шкалу прогресса прокрутки, например:
<main>
<section>
<article>
...
</article>
</section>
<div id="progress"></div>
</main>
#progress{
width: 100%;
height: 10px;
background-color: #c00bc0;
position: fixed;
top: 0;
left: 0;
transform-origin: 0 50%;
animation: progress linear;
animation-timeline: scroll();
}
В этом коде мы закрепляем индикатор прогресса чтения в верхней части области просмотра и масштабируем его вперед и назад по оси X
в зависимости от положения скроллера. Вот результат:
Именованная временная шкала положения прокрутки
Именованная временная шкала положения прокрутки обеспечивает явный контроль над выбором скроллера. Вместо того, чтобы полагаться на автоматический поиск с помощью API, он позволяет назначать уникальные идентификаторы или имена конкретным контейнерам с полосами прокрутки.
Этот подход помогает точно определить и использовать временную шкалу прокрутки идентифицированного контейнера. Этот метод особенно полезен в тех случаях, когда веб-страница имеет несколько временных шкал и анонимного автоматического поиска недостаточно.
Чтобы реализовать именованную временную шкалу позиции прокрутки, задайте для свойства Scroll-Timeline-Name
нужного контейнера прокрутки значение имени по вашему выбору. Убедитесь, что значение имеет префикс --
, например:
scroll-timeline-name: --my-timeline;
Как и в случае с анонимной временной шкалой прокрутки, вы можете настроить ось, используя свойство Scroll-Timeline-axis
. Это свойство использует те же значения, что и аргумент <axis>
в анонимном методе:
scroll-timeline-axis: block;
В отличие от свойства animation-timeline
шкалы, вы можете объединить свойства scroll-timeline-name
и scroll-timeline-axis
в одно сокращенное свойство: прокрутку-временной шкалы. Это означает, что вы можете определить оба свойства одновременно, вместо того, чтобы делать это по отдельности.
Вот пример, демонстрирующий, как работает именованный прогресс прокрутки:
.source {
scroll-timeline-name: --my-timeline;
scroll-timeline-axis: inline;
}
You can simply write:
.source {
scroll-timeline: --my-timeline inline;
}
Вы можете обновить базовую разметку предыдущей демонстрации и добавить на страницу еще один контейнер прокрутки:
<div id="galaxies" style="--num-images: 3">
<div id="galaxy-container">
<div class="galaxy_progress"></div>
<div class="andromenda galaxy_entry">
<img src="./andromeda.jpg" />
</div>
<div class="pinwheel galaxy_entry">
<img src="./pinwheel.jpg" />
</div>
<div class="milky-way galaxy_entry">
<img src="./milky.jpg" />
</div>
</div>
</div>
В этом коде мы создаем контейнер galaxy
с тремя дочерними изображениями и элементом galaxy_progres
, который будет позиционироваться абсолютно по отношению к контейнеру galaxies
.
Далее, давайте дадим galaxy-container
идентификатор и inline
ось, используя сокращенное свойство scroll-timeline
шкалы. Затем мы прикрепим его к анимационному элементу (в данном случае элементу galaxy_progress
), используя свойство animation-timeline
:
#galaxy-container{
overflow-x: scroll;
scroll-snap-type: x mandatory;
display: flex;
scroll-timeline: --galaxies inline;
}
@keyframes galaxies_animation {
to { transform: scaleX(1); }
}
.galaxy_progress {
position: absolute;
top: 0;
left: 0;
width: 500px;
height: 10px;
background-color: #c00bc0;
transform: scaleX(calc(1 / var(--num-images)));
animation: auto galaxies_animation linear forwards;
animation-timeline: --galaxies;
}
Здесь мы устанавливаем идентификатор --inner_timeline
для .inner-container
и ссылаемся на него с помощью свойства animation-timeline
анимации .gallery-progress
. Вот результат:
Может показаться нелогичным использовать здесь именованную временную шкалу прогресса прокрутки, поскольку анонимная временная шкала прогресса могла бы легко использовать ближайший контейнер-предок с полосой прокрутки с использованием аргумента scroll(nearest inline)
(в данном случае .inner-container
). Но на самом деле, поскольку .gallery-progress
абсолютно позиционирован, временная шкала анимации пропустила бы .inner-container
и использовала бы корневой скроллер, который является ближайшим предком, который позиционируется относительно.
Ближайший аргумент учитывает элемент, который может повлиять на его размер и положение. Поскольку элемент .gallery-progress
позиционируется абсолютно, а его ближайший родительский элемент не позиционируется относительно, он перейдет к ближайшему предку, который позиционирован относительно, и будет использовать его временную шкалу.
Прокручивать диапазоны шкалы прогресса
По умолчанию анимация, связанная с временной шкалой прокрутки и просмотра, заключается в прикреплении ко всему диапазону страницы. Для временной шкалы прокрутки диапазон прокрутки составляет от 0% до 100%. Для временной шкалы просмотра она охватывает период от первоначальной видимости элемента на одном краю до его появления на противоположном краю.
Свойство анимации-диапазона вступает в действие, когда вам нужно настроить эти значения и переопределить поведение по умолчанию. Вы можете использовать свойство анимации-диапазона, чтобы привязать анимацию прокрутки или просмотра временной шкалы к определенным начальному и конечному диапазонам на временной шкале:
animation-range: <range-start> <range-end>;
Если вы хотите, чтобы анимация запускалась только в течение первых 40%
веб-страницы и заканчивалась на 80%
, вы можете определить ее следующим образом:
animation-range: 40% 80%;
Диапазон анимации также можно указать в значениях высоты просмотра (vh)
, например:
Свойство анимации-диапазона принимает разные значения в зависимости от временной шкалы, с которой оно используется. Приведенный выше пример будет работать только для временной шкалы прогресса прокрутки, поскольку указанные значения находятся в пределах диапазона начальных и конечных значений временной шкалы прогресса прокрутки. Позже в этой статье мы рассмотрим, как определить диапазон анимации для временной шкалы прогресса просмотра.
Просмотр графика прогресса
Временная шкала прогресса просмотра также связана с позицией прокрутки контейнера, но по отношению к прогрессу элемента внутри контейнера. Проще говоря, относительное положение элемента в скроллере определяет ход временной шкалы. Прогресс временной шкалы начинается в тот момент, когда элемент впервые пересекает скроллер, и заканчивается, когда элемент больше не пересекает скроллер.
Временная шкала прогресса просмотра аналогична API Intersection Observer
в JavaScript. Вы можете использовать как анонимный метод, так и методы Names
, чтобы создать временную шкалу прогресса просмотра.
Анонимный просмотр графика прогресса
Чтобы создать анонимную временную шкалу прогресса просмотра, вы воспользуетесь функцией view()
и передадите ее как значение animation-timeline
шкалы:
animation-timeline: view();
Функция view()
принимает аргумент <axis>
и необязательный аргумент <view-timeline-inset>
. Аргумент <axis>
идентичен тому, который используется в функции scroll()
; он используется для определения того, какую ось отслеживать, и принимает одни и те же значения.
Аргумент <view-timeline-inset>
используется для указания значения смещения для настройки границ, когда элемент считается находящимся в представлении (или за его пределами). Значение смещения может быть положительным или отрицательным.
Легко добавить временную шкалу прогресса просмотра к любой анимации веб-страницы, используя анонимный метод. В качестве примера вы можете использовать следующий код, чтобы изображения на нашей демонстрационной странице появлялись при прокрутке:
@keyframes image-reveal {
from {
opacity: 0;
clip-path: inset(0% 30% 0% 30%);
}
to {
opacity: 1;
clip-path: inset(0% 0% 0% 0%);
}
}
.images {
animation: image-reveal both;
animation-timeline: view();
}
Временная шкала выполнения именованного просмотра
Вы можете создать именованную временную шкалу просмотра, используя тот же метод, который используется для временной шкалы прокрутки. Просто установите идентификатор (или name
) и axis
с теми же свойствами и значениями, но замените префикс прокрутки на представление:
.nested-container{
view-timeline-name: --image-reveal;
view-timeline-axis: block;
}
@keyframes image-reveal {
from {
opacity: 0;
clip-path: inset(0% 30% 0% 30%);
}
to {
opacity: 1;
clip-path: inset(0% 0% 0% 0%);
}
}
.nested-images{
animation: image-reveal both;
animation-timeline: --image-reveal;
}
Этот код создаст тот же визуальный вывод, что и анонимный метод, но для вложенного скроллера и его дочерних изображений.
Просмотр диапазонов графика прогресса
Значение диапазона анимации варьируется в зависимости от используемой временной шкалы. В случае с временной шкалой просмотра принимается значение имени диапазона, а не процентное значение. Ниже приведены допустимые значения имени диапазона для временной шкалы просмотра:
- cover: устанавливает диапазон временной шкалы просмотра на значения, которые гарантируют, что элемент полностью покрыт скроллером во время просмотра временной шкалы.
- entry: устанавливает начальное значение диапазона временной шкалы просмотра на 0% и устанавливает конечное значение на процент видимости элемента, когда он находится внутри скроллера.
- exit: устанавливает начальное значение диапазона временной шкалы просмотра в процентах от видимости элемента, когда он находится внутри скроллера, и устанавливает конечное значение на 100 %.
- entry-crossing: устанавливает начальное значение и конечное значение диапазона временной шкалы просмотра в процентах от видимости элемента, когда он впервые виден на одном краю скроллера и когда он полностью виден внутри скроллера соответственно.
- exit-crossing: устанавливает начальное и конечное значение диапазона временной шкалы просмотра в процентах от видимости элемента, когда он находится внутри скроллера и когда он достигает противоположного края полосы прокрутки соответственно.
- contain: указывает, что анимация начнется и закончится в пределах области прокрутки.
Эти имена диапазонов часто комбинируются со смещением диапазона при определении значений range-start
и range-end
для свойства animation-range
. Смещение диапазона — это процентное значение, которое используется для определения положения элемента относительно имени диапазона, с которым он объединен.
Например, если вы хотите, чтобы анимация начиналась на полпути в момент ее пересечения с областью прокрутки, установите значение range-start
равным 50%
. Таким образом, анимация запустится и будет прогрессировать до 50%
, прежде чем она попадет в область просмотра. Тот же подход применяется к конечному значению диапазона:
animation-range: entry 25% cover 50%;
Ограничения
Совместимость браузера — серьезная проблема, с которой вы столкнетесь при реализации пользовательского интерфейса с поддержкой прокрутки через CSS. Большинство новых CSS API и даже некоторые старые, которые предоставляют улучшенные возможности для проектирования пользовательского интерфейса с поддержкой прокрутки, все еще являются экспериментальными и еще не имеют широкой поддержки в различных браузерах.
Например, на момент написания API-интерфейсы scroll
и view
в настоящее время поддерживаются только в браузерах на базе Chromium, а также в браузерах Firefox с флагом функции.
Еще одним ограничением являются проблемы с производительностью и доступностью, которые часто возникают при работе с анимацией, управляемой прокруткой. Сложность и частота анимации могут привести к таким проблемам, как зависания, задержки или даже разряд батареи на определенных устройствах. Кроме того, эти анимации могут мешать работе пользователя с прокруткой, а также инструментам специальных возможностей, таким как программы чтения с экрана и навигация с помощью клавиатуры.
Один из способов решения этих проблем — оптимизировать анимацию, чтобы обеспечить плавную работу без ущерба для удобства пользователя. Кроме того, предоставление возможности отключения анимации может улучшить доступность для пользователей, которым она может показаться мешающей.
Другая эффективная стратегия — использование polyfills JavaScript. Polyfills расширяют функциональность функций CSS, позволяя им работать в браузерах, не имеющих встроенной поддержки. Вы можете использовать polyfills
JavaScript, чтобы улучшить совместимость и обеспечить согласованную работу анимации, управляемой прокруткой, в разных браузерах.
Расширение возможностей с помощью JavaScript
Новые функции CSS для анимации, управляемой прокруткой, являются мощными и декларативными, но они еще не широко поддерживаются всеми браузерами. Чтобы обеспечить кросс-браузерную совместимость и доступность, вы можете использовать JavaScript для улучшения или заполнения анимаций, управляемых прокруткой.
С этой задачей могут помочь несколько библиотек и фреймворков, например ScrollTrigger, ScrollMagic, Framer Motion и старый добрый Intersection Observer API. Эти инструменты предоставляют больше возможностей и гибкости для простого создания сложных и интерактивных анимаций, управляемых прокруткой.
Другой способ расширить возможности — использовать интерфейсы ScrollTimeline
и ViewTimeline
спецификации анимации, управляемой прокруткой. Вы можете использовать эти классы для создания анимации прокрутки и просмотра временной шкалы с помощью JavaScript, создавая взаимодействия, аналогичные их аналогам CSS. Они полезны для тех, кто предпочитает использовать JavaScript, а также в тех случаях, когда JavaScript требуется для дополнительных функций.
Классы ScrollTimeline
и ViewTimeline
принимают такие параметры, как исходный элемент, ось, ориентация, диапазон и диапазон временной шкалы. Вы также можете связать эти временные шкалы с анимацией, созданной с помощью интерфейса анимации, и управлять имя с помощью таких методов, как play
, resume
, pause
, cancel
или reverse
.
Чтобы создать прокрутку и просмотр временной шкалы с помощью JavaScript, создайте новый объект ScrollTimeline
или ViewTimeline
с помощью конструктора. Затем укажите исходный элемент и любое из следующих дополнительных свойств: axis
, orientation
и range
:
const timeline = new ScrollTimeline({
source: document.documentElement, // The document element as the source
axis: "block",
});
Здесь мы устанавливаем элемент document
в качестве source
; это привяжет анимацию к временной шкале корневой позиции прокрутки.
Затем создайте new Animation
, используя конструктор animation
. Вы можете передать объект ключевого кадра, чтобы указать свойства и значения анимации, а также объект параметров, чтобы указать продолжительность анимации (duration
), easing
и fill
.
Вам также потребуется передать объект ScrollTimeline
или ViewTimeline
в качестве параметра временной шкалы, чтобы связать анимацию с временной шкалой:
const animation = new Animation(
/* The keyframe object*/
{
transform: ["rotate(0deg)", "rotate(360deg)"],
},
/* The options object*/
{
duration: 100,
fill: "both",
}
/*Link the animation to the timeline*/
animation.timeline = timeline;
);
Заключение
Концепция пользовательского интерфейса с поддержкой прокрутки относится к различным интерактивным элементам на веб-странице, которые динамически настраиваются, прикрепляются или фиксируются в нужном положении при перемещении большого пальца полосы прокрутки. В этой статье мы рассмотрели создание пользовательского интерфейса с поддержкой прокрутки только с помощью CSS, чтобы обеспечить большую интерактивность и лучший пользовательский опыт без негативного влияния на производительность системы.
Существует множество способов реализовать дизайн с поддержкой прокрутки для ваших веб-приложений. Возможности практически безграничны и ограничены только воображением.
Удачного взлома!
Ваш интерфейс нагружает процессор ваших пользователей?
Поскольку веб-интерфейсы становятся все более сложными, ресурсоемкие функции требуют от браузера все большего и большего. Если вы заинтересованы в мониторинге и отслеживании использования ЦП на стороне клиента, использования памяти и многого другого для всех ваших пользователей в рабочей среде, попробуйте LogRocket.
LogRocket похож на видеорегистратор для веб- и мобильных приложений, записывающий все, что происходит в вашем веб-приложении, мобильном приложении или веб-сайте. Вместо того, чтобы гадать, почему возникают проблемы, вы можете агрегировать и составлять отчеты по ключевым показателям производительности внешнего интерфейса, воспроизводить пользовательские сеансы вместе с состоянием приложения, регистрировать сетевые запросы и автоматически выявлять все ошибки.
Модернизируйте способы отладки веб- и мобильных приложений — начните мониторинг бесплатно.