DevGang
Авторизоваться

Реализация состояния пользовательского интерфейса с поддержкой прокрутки с помощью 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 похож на видеорегистратор для веб- и мобильных приложений, записывающий все, что происходит в вашем веб-приложении, мобильном приложении или веб-сайте. Вместо того, чтобы гадать, почему возникают проблемы, вы можете агрегировать и составлять отчеты по ключевым показателям производительности внешнего интерфейса, воспроизводить пользовательские сеансы вместе с состоянием приложения, регистрировать сетевые запросы и автоматически выявлять все ошибки.

Модернизируйте способы отладки веб- и мобильных приложений — начните мониторинг бесплатно.

Источник:

#JavaScript #CSS #HTML
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

В этом месте могла бы быть ваша реклама

Разместить рекламу