Анимации, управляемые прокруткой, являются распространенным шаблоном UX в Интернете. Анимация, управляемая прокруткой, связана с позицией прокрутки контейнера прокрутки. Это означает, что при прокрутке вверх или вниз связанная анимация перемещается вперед или назад в прямом ответе. Примерами этого являются такие эффекты, как фоновые изображения параллакса или индикаторы чтения, которые перемещаются при прокрутке.
Разработчики обычно создавали анимации, управляемые прокруткой, используя JavaScript для реагирования на события прокрутки в основном потоке. Это затрудняет создание производительных анимаций, управляемых прокруткой, которые синхронизируются с прокруткой, поскольку события прокрутки доставляются асинхронно, и часто приводит к подтормаживанию из-за нахождения в основном потоке.
Однако, как часть новых функций CSS и пользовательского интерфейса, реализованных в браузерах , теперь вы можете создавать декларативные анимации, управляемые прокруткой. С помощью Scroll Timelines и View Timelines, новых концепций, которые интегрируются с существующим Web Animations API (WAAPI) и CSS Animations API , теперь вы можете иметь шелковисто-плавные анимации, управляемые прокруткой, работающие вне основного потока, всего с несколькими строками кода. В этом исследовании случая узнайте, как Tokopedia, redBus и Policybazaar уже получают выгоду от этой новой функции.
Токопедия
Tokopedia заменила свои предыдущие пользовательские реализации JavaScript на анимацию с прокруткой, чтобы оптимизировать производительность страниц и улучшить общий опыт просмотра во всей воронке конверсии электронной коммерции.
Нам удалось сократить до 80% строк кода по сравнению с использованием обычных событий прокрутки JavaScript, и мы заметили, что средняя загрузка ЦП снизилась с 50% до 2% при прокрутке — Энди Вихалим , старший инженер-программист, Tokopedia
Код
Следующая реализация использует функцию scroll()
для установки анонимной временной шкалы прогресса прокрутки для управления ходом анимации CSS. Видимость верхней липкой полосы изменяется в зависимости от положения прокрутки в пределах определенного animationRange
.
const toggleBar = keyframes({
to: { height: 48 },
});
export const cssWrapper = css({
position: 'fixed',
left: 0,
width: '100vw',
pointerEvents: 'none',
marginTop: 120,
height: 0,
overflow: 'hidden',
display: 'flex',
flexDirection: 'column',
justifyContent: 'flex-end',
animation: `${toggleBar} linear both`,
animationTimeline: 'scroll()',
animationRange: '20px 70px',
});
redBus
redBus использует разные анимации для мобильных устройств и ПК на своей целевой странице «Что делать» , которая отображается на ранней стадии воронки конверсии для всех пользователей. С помощью анимации, управляемой прокруткой, они смогли заменить эти пользовательские реализации JavaScript на CSS, чтобы добиться того же эффекта.
Варианты использования
Фотогалерея с функциями Image Reveal (для мобильных устройств) и Cover Flow (для настольных компьютеров).
Код (мобильный)
В предыдущем примере Tokopedia использовала анонимную временную шкалу прогресса прокрутки . В следующем коде redBus использует именованную временную шкалу прогресса просмотра . Анимация изменяет opacity
и clip-path
элемента <img>
в пределах определенного animation-range
внутри ближайшего предка элемента-скроллера, которым в данном случае является скроллер фотогалереи.
const reveal = keyframes`
from {
opacity: 0;
clip-path: inset(45% 20% 45% 20%);
}
to {
opacity: 1;
clip-path: inset(0% 0% 0% 0%);
}`
const CardImage = styled.div`
width: 100%;
height: 100%;
img {
border-top-left-radius: 0.75rem;
border-top-right-radius: 0.75rem;
height: 100%;
width: 100%;
object-fit: cover;
view-timeline-name: --revealing-image;
view-timeline-axis: block;
/* Attach animation, linked to the View Timeline */
animation: linear ${reveal} both;
animation-timeline: --revealing-image;
/* Tweak range when effect should run*/
animation-range: entry 25% cover 50%;
}
`;
Мы очень рады видеть эту функцию, поскольку она представляет собой идеальное сочетание производительности с лучшим опытом, повышая наши сигналы Page Experience для SEO. Вдобавок ко всему, минимальная кривая обучения делает ее обязательной для каждого веб-сайта электронной коммерции. Мы также получили положительные отзывы и поддержку от других команд, чтобы использовать SDA для большего количества пользовательских путешествий. — Амит Кумар , старший инженер-менеджер, redBus .
Policybazaar
Сравнение страховых планов — это повторяющееся ключевое действие, выполняемое пользователями для управления процессом принятия решений. Используя анимацию, управляемую прокруткой, Policybazaar уменьшил размер низкоприоритетных элементов в ответ на прокрутку таблицы пользователем. Это привело к изящному опыту прокрутки и улучшению читаемости.
Благодаря анимации, управляемой прокруткой, мы смогли максимально увеличить область просмотра, чтобы пользователь мог сравнивать планы, обеспечивая целенаправленное и упорядоченное чтение . — Ришаб Мехротра , руководитель отдела дизайна подразделения страхования жизни, PolicyBazaar .
animate-timeline
в таблице сравнения планов в инвестиционном и жизненном бизнесе (направление деятельности). Код
Подобно предыдущему примеру из Tokopedia, Policybazaar использует функцию scroll()
для установки анонимной временной шкалы прогресса прокрутки для управления ходом анимации CSS. В этом случае происходит уменьшение размера шрифта и исчезновение заголовка на основе позиции прокрутки в пределах определенного animation-range
.
@supports (animation-timeline: scroll()) {
.plan-comparison .inner-header {
animation: move-and-fade-header linear both;
}
.plan-comparison .left-side {
animation: shrink-name linear both;
}
.plan-comparison .inner-header, .plan-comparison .left-side {
animation-timeline: scroll();
animation-range: 0 150px;
}
}
@keyframes move-and-fade-header {
to {
translate: 0% -5%;
top:103px;
}
}
@keyframes shrink-name {
to {
font-size: 1.5rem;
}
}
Анимация, управляемая прокруткой, как распространенная модель на всем пути пользователя
Все представленные компании электронной коммерции использовали анимацию, управляемую прокруткой, на страницах с карточками, анимируя карточки, чтобы привлечь к ним внимание пользователя. В следующих примерах показаны эффекты прокрутки на карточках в разных частях пути пользователя. Обычно это достигается с помощью анонимной временной шкалы прогресса просмотра для управления ходом пользовательской анимации CSS, как показано в следующем фрагменте CSS.
@keyframes animate-in {
0% { opacity: 0; transform: translateY(10%); }
100% { opacity: 1; transform: translateY(0); }
}
@keyframes animate-out {
0% { opacity: 1; transform: translateY(0); }
100% { opacity: 0; transform: translateY(-10%); }
}
.flyin_animate {
animation: animate-in linear forwards;
animation-timeline: view();
animation-range: entry;
}
redBus (Главная страница)
Policybazaar (страница со списком товаров)
Tokopedia (страница сведений о продукте)
Что следует учитывать при использовании API анимации с помощью прокрутки
Можно использовать полифиллы для анимаций, управляемых прокруткой, для неподдерживающих браузеров, например, с помощью полифилла Scroll-timeline . Если вы это сделаете, это потребует дополнительного тестирования, чтобы убедиться, что он хорошо работает вместе с вашим фреймворком, и что браузеры, использующие полифиллы, не испытывают сбоев анимации или дерганий.
Из CSS вы можете использовать @supports
для проверки поддержки animation-timeline перед использованием анимации, управляемой прокруткой. Например:
@supports (animation-timeline: scroll()) {
}
Ресурсы
- Демонстрации анимации, управляемой прокруткой
- Анимируйте элементы при прокрутке с помощью анимации, управляемой прокруткой
- Codelab: Начало работы с анимацией, управляемой прокруткой, в CSS
- Расширение Chrome: отладчик анимации с помощью прокрутки
- Прокрутка временной шкалы Polyfill
- Хотите сообщить об ошибке или новой функции? Мы хотим услышать от вас !
Ознакомьтесь с другими статьями этой серии, в которых рассказывается о том, как компании электронной коммерции получили выгоду от использования новых функций CSS и пользовательского интерфейса, таких как View Transitions, Popover, Container Queries и селектор has()
.