Прекрасный опыт прокрутки — без библиотек

Прекрасный опыт прокрутки - без библиотек

От автора: одной из областей, где Интернет традиционно отстает от нативных платформ, является воспринимаемая «привлекательность» приложения. Частично это восприятие происходит от того, как пользовательский интерфейс реагирует на взаимодействие с пользователем, включая прокрутку содержимого.

Столкнувшись с ограничениями веб-платформы, разработчики часто обращаются к библиотекам и фреймворкам JavaScript, чтобы изменить процесс прокрутки веб-страницы — иногда называемый “scroll-jacking” — не всегда хорошо, если он реализован без должного учета пользовательского опыта. Увеличение количества библиотек также может привести к раздуванию страницы и снижению производительности сайта. Но с помощью относительно новой спецификации CSS Scroll Snap мы можем контролировать поведение прокрутки веб-страницы (до некоторой степени), используя веб-стандарты, не прибегая к тяжелым библиотекам. Давайте посмотрим, как.

Scroll Snap

Пользователь может управлять положением прокрутки веб-страницы несколькими способами, например, используя мышь, сенсорный жест или клавиши со стрелками. В отличие от линейной прокрутки, где скорость прокрутки отражает скорость контроллера, спецификация Scroll Snap позволяет веб-странице привязываться к определенным точкам при прокрутке пользователя. Для этого нам нужен элемент с фиксированной высотой, который будет выполнять роль контейнера прокрутки, и прямые дочерние элементы этого элемента будут определять точки привязки. Чтобы продемонстрировать это, вот пример HTML, который состоит из div, содержащего четыре элемента section:

<div class="scroll-container"> <section> <h2>Section 1</h2> </section> <section> <h2>Section 2</h2> </section> <section> <h2>Section 3</h2> </section> <section> <h2>Section 4</h2> </section>
</div>

Привязка прокрутки требует наличия двух основных свойств CSS: scroll-snap-type и scroll-snap-align. scroll-snap-type применяется к элементу контейнера прокрутки и принимает в качестве значения два ключевых слов. Это указывает браузеру:

Направление для привязки

Является ли привязка обязательной

scroll-snap-align применяется к дочерним элементам — в нашем случае section. Нам также нужно установить фиксированную высоту для контейнера прокрутки и соответствующее значение свойства overflow — scroll.

.scroll-container { height: 100vh; overflow-y: scroll; scroll-snap-type: y mandatory;
} section { height: 100vh; scroll-snap-align: center;
}

В приведенном выше примере я устанавливаю направление в свойстве scroll-snap-type — y, чтобы указать привязку по вертикали. Второе значение указывает, что привязка является обязательной. Это означает, что когда пользователь прекращает прокрутку, его позиция прокрутки всегда привязывается к ближайшей точке привязки. Альтернативное значение proximity, которое определяет, что позиция прокрутки пользователя будет привязана только в том случае, если он остановит прокрутку вблизи точки привязки. (Это зависит от браузера — он определяет, что считает порогом близости.)

Если у вас есть содержимое неопределенной длины, которое может быть больше, чем высота контейнера прокрутки (в данном случае 100vh), то использование значения mandatory может вызвать скрытие некоторого содержимого над или под видимой областью, поэтому это не рекомендуется. Но если вы знаете, что ваш контент всегда будет вписываться в область просмотра, то mandatory может обеспечить более согласованное взаимодействие с пользователем.

В этом примере я устанавливаю для контейнера прокрутки и для каждого из разделов высоту 100vh, которая влияет на процесс прокрутки всей веб-страницы. Но привязка прокрутки также может быть реализована на меньших компонентах. Установка привязки прокрутки по оси X (или по оси) может да эффекту карусели.

В этой демонстрации вы можете горизонтально прокручивать разделы:

Intersection Observer API

Благодаря реализации CSS, приведенной выше, наша веб-страница уже выглядит более нативно. Чтобы улучшить это, мы могли бы добавить некоторые переходы и анимацию на основе прокрутки. Для этого нам понадобится немного Javascript, использующего Intersection Observer API. Это позволит нам создать наблюдатель, который отслеживает элементы, пересекающиеся с окном просмотра, вызывая функцию обратного вызова, когда это происходит. Это более эффективно, чем библиотеки, которые полагаются на постоянное прослушивание событий прокрутки.

Мы можем создать наблюдателя, который наблюдает за каждым из наших разделов прокрутки, входящих и выходящих из окна просмотра:

const sections = [...document.querySelectorAll('section')] const options = { rootMargin: '0px', threshold: 0.25
} const callback = (entries) => { entries.forEach((entry) => { if (entry.intersectionRatio >= 0.25) { target.classList.add("is-visible"); } else { target.classList.remove("is-visible"); } })
} const observer = new IntersectionObserver(callback, options) sections.forEach((section, index) => { observer.observe(section)
})

В этом примере функция обратного вызова запускается всякий раз, когда один из наших разделов пересекает контейнер на 25% (используя опцию threshold). Функция обратного вызова добавляет класс is-visibleк разделу, если он имеет не менее 25% пересечения с наблюдаемым контейнером, когда происходит пересечение (которое вступит в силу при появлении элемента в окне просмотра), и удаляет его в противном случае (когда элемент выходит из окна просмотра). Затем мы можем добавить немного CSS для контент каждого из этих разделов для перехода:

section .content { opacity: 0:
} section.is-visible .content { opacity: 1; transition: opacity 1000ms:
}

Данная демонстрация иллюстрирует это в действии:

Конечно, вы могли бы реализовать некоторые более причудливые эффекты перехода и анимации в CSS или JS!

Кроме того, стоит отметить, что на практике мы не должны устанавливать значение opacity: 0 по умолчанию, не принимая во внимание опыт, если JavaScript не загружается. В этом случае пользователь вообще не увидит никакого контента! Есть разные способы справиться с этим: мы можем добавить класс .no-js для body (который мы удаляем при загрузке с помощью JS) и установить для него стили по умолчанию, или мы можем установить начальный стиль (до перехода) с помощью JS вместо CSS.

Position: sticky

Есть еще одно свойство CSS, которое, как мне кажется, может помочь в работе с прокруткой, и это свойство position. В отличие от position: fixed, которое блокирует положение элемента относительно ближайшего предка и не изменяется, position: sticky больше похож на временную блокировку. Элемент со значением позиции sticky станет фиксированным только до тех пор, пока не достигнет порога своего родителя, после чего он возобновит относительное позиционирование.

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

Поддержка браузерами и откат

Свойства scroll-snap-type и scroll-snap-align достаточно хорошо поддерживается. Первому требуется префикс для Edge и IE, а более старые версии Safari не поддерживают значения осей. В новых версиях Safari это работает довольно хорошо. Intersection Observer также имеет хороший уровень поддержки, за исключением IE.

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

@supports (scroll-snap-type: y mandatory) { .scroll-container { height: 100vh; overflow-y: scroll; scroll-snap-type: y mandatory; } section { height: 100vh; scroll-snap-align: center; }
}

Приведенный выше код исключает MS Edge и IE, так как они не поддерживают значения осей. Если вы хотите поддерживать их, вы можете сделать это с помощью вендрного префикса и вместо этого использовать @supports (scroll-snap-type: mandatory).

Собираем все вместе

Эта демонстрация объединяет все три эффекта, рассмотренных в данной статье.

Заключение

Уделить время на моделирование на основе прокрутки некоторым может показаться глупым или легкомысленным занятием. Но я считаю, что это важная часть позиционирования, как жизнеспособной альтернативы нативным приложениям, сохранения его открытости и доступности. Несмотря на то, что эти новые функции CSS не предлагают всех элементов управления, которые мы могли бы ожидать от полнофункциональной библиотеки JS, у них есть главное преимущество: простота и надежность. Используя веб-стандарты, где это возможно, мы можем получить лучшее из обоих миров: привлекательные и аккуратные сайты, которые соответствуют ожиданиям клиентов, с дополнительным преимуществом повышения производительности для пользователей.

Автор: Michelle Barker

Источник: https://24ways.org

Редакция: Команда webformyself.