Хорошо контролируемая прокрутка с помощью CSS Scroll Snap.

Создайте хорошо контролируемую прокрутку, объявив позиции привязки прокрутки.

Роберт Флэк
Robert Flack
Маджид Валипур
Majid Valipour

Функция CSS Scroll Snap позволяет веб-разработчикам создавать хорошо контролируемые возможности прокрутки, объявляя позиции привязки прокрутки. Статьи с разбивкой на страницы и карусели изображений — два часто используемых примера. CSS Scroll Snap предоставляет простой в использовании и согласованный API для создания популярных шаблонов UX.

Фон

Аргументы в пользу привязки прокрутки

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

Главный недостаток прокрутки — отсутствие точности. Редко когда прокрутка выравнивается по абзацу или предложению. Это еще более заметно для содержимого с разбивкой на страницы или по пунктам со значимыми границами, когда прокрутка заканчивается в середине страницы или изображения, оставляя его частично видимым. Эти варианты использования выигрывают от хорошо контролируемой прокрутки.

Веб-разработчики уже давно полагаются на решения на основе JavaScript для управления прокруткой, чтобы устранить этот недостаток. Однако решения на основе JavaScript не могут обеспечить полную точность решения из-за отсутствия примитивов настройки прокрутки или доступа к составной прокрутке. CSS Scroll Snap обеспечивает быстрое, высокоточное и простое в использовании решение, которое одинаково работает во всех браузерах.

CSS Scroll Snap позволяет веб-авторам помечать каждый контейнер прокрутки границами для завершения операций прокрутки. Затем браузеры выбирают наиболее подходящую конечную позицию в зависимости от особенностей операции прокрутки, макета и видимости контейнера прокрутки, а также деталей позиций привязки, а затем плавно анимируют ее. Возвращаясь к нашему предыдущему примеру, когда пользователь заканчивает прокручивать карусель, ее видимое изображение встает на место. JavaScript не требует никаких настроек прокрутки.

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

CSS-прокрутка

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

Для контейнера прокрутки можно включить привязку прокрутки с помощью свойства scroll-snap-type . Это сообщает браузеру, что ему следует рассмотреть возможность привязки этого контейнера прокрутки к позициям привязки, созданным его потомками. scroll-snap-type определяет ось, по которой происходит прокрутка: x , y или both , а также строгость привязки: mandatory , proximity . Подробнее об этом позже.

Положение привязки можно создать, объявив желаемое выравнивание элемента. Эта позиция представляет собой смещение прокрутки, при котором ближайший контейнер прокрутки предка и элемент выравниваются, как указано для данной оси. По каждой оси возможны следующие выравнивания: start , end , center .

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

Пример различных выравниваний по горизонтальной оси прокрутки.

Следующие примеры иллюстрируют, как использовать эти понятия.

Распространенным вариантом использования привязки прокрутки является карусель изображений. Например, чтобы создать горизонтальную карусель изображений, которая привязывается к каждому изображению при прокрутке, мы можем указать контейнеру прокрутки наличие обязательного scroll-snap-type на горизонтальной оси. установите для каждого изображения значение scroll-snap-align: center чтобы гарантировать, что привязка центрирует изображение внутри карусели.

#gallery {
  scroll-snap-type: x mandatory;
  overflow-x: scroll;
  display: flex;
}

#gallery img {
   scroll-snap-align: center;
}
<div id="gallery">
  <img src="cat.jpg">
  <img src="dog.jpg">
  <img src="another_cute_animal.jpg">
</div>

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

Посмотреть демо | Источник

Пример: страница продукта, пройденного в путешествии.

Другой распространенный случай, когда привязка прокрутки может принести пользу, — это страницы с несколькими логическими разделами для вертикальной прокрутки, например типичная страница продукта. scroll-snap-type: y proximity; более естественно подходит для подобных случаев. Это не мешает, когда пользователь прокручивает до середины определенного раздела, но также привязывается и привлекает внимание к новому разделу, когда он прокручивает достаточно близко.

Вот как этого можно достичь:

article {
  scroll-snap-type: y proximity;
  /* Reserve space for header plus some extra space for sneak peeking. */
  scroll-padding-top: 15vh;
  overflow-y: scroll;
}
section {
  /* Snap align start. */
  scroll-snap-align: start;
}
header {
  position: fixed;
  height: 10vh;
}
<article>
  <header> Header </header>
  <section> Section One </section>
  <section> Section Two </section>
  <section> Section Three </section>
</article>

Отступы и поля прокрутки

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

Свойство scroll-padding — это новое свойство CSS, которое можно использовать для настройки эффективной видимой области контейнера прокрутки или порта привязки, который используется при расчете выравнивания привязки прокрутки. Свойство определяет вставку в поле заполнения контейнера прокрутки. В нашем примере сверху была добавлена ​​дополнительная вставка 15vh , которая указывает браузеру рассматривать нижнюю позицию, 15vh ниже верхнего края контейнера прокрутки, в качестве его вертикального начального края для привязки прокрутки. При привязке начальный край целевого элемента привязки станет заподлицо с этой новой позицией, оставляя пространство выше.

Свойство scroll-margin определяет начальную величину, используемую для настройки эффективного поля цели привязки, аналогично тому, как работает scroll-padding в контейнере привязной прокрутки.

Возможно, вы заметили, что в этих двух свойствах нет слова « snap ». Это сделано намеренно, поскольку они фактически изменяют поле для всех соответствующих операций прокрутки, а не просто привязку прокрутки. Например, Chrome учитывает их при расчете размера страницы для операций прокрутки страниц, таких как PageDown и PageUp, а также при расчете объема прокрутки для операции Element.scrollIntoView() .

Посмотреть демо | Источник

Взаимодействие с другими API прокрутки

API прокрутки DOM

Привязка прокрутки происходит после всех операций прокрутки, включая те, которые инициированы сценарием. Когда вы используете такие API, как Element.scrollTo , браузер рассчитает предполагаемую позицию прокрутки операции, а затем применит соответствующую логику привязки, чтобы найти окончательное местоположение привязки. Таким образом, пользовательскому сценарию не нужно выполнять какие-либо ручные вычисления для привязки.

Плавная прокрутка

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

Поведение при чрезмерной прокрутке

API поведения при чрезмерной прокрутке контролирует, как прокрутка связана между несколькими элементами, и на него не влияет привязка прокрутки.

Предостережения и лучшие практики

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

Во многих случаях привязку прокрутки можно добавить в качестве улучшения без необходимости обнаружения функции. При необходимости используйте @supports или CSS.supports , чтобы обнаружить поддержку CSS Scroll Snap. Избегайте использования scroll-snap-type , который также присутствует в устаревшей спецификации.

Обнаружение функций в CSS

@supports (scroll-snap-align: start) {
  article {
    scroll-snap-type: y proximity;
    scroll-padding-top: 15vh;
    overflow-y: scroll;
  }
}

Обнаружение функций в JavaScript

if (CSS.supports('scroll-snap-align: start')) {
  // use css scroll snap
} else {
  // use fallback
}

Не предполагайте, что программные API-интерфейсы прокрутки, такие как Element.scrollTo всегда завершаются при запрошенном смещении прокрутки. Привязка прокрутки может регулировать смещение прокрутки после завершения программной прокрутки. Обратите внимание, что это не было хорошим предположением даже до привязки прокрутки, поскольку прокрутка могла быть прервана по другим причинам, но это особенно касается привязки прокрутки.

Будущая работа

Опыт прокрутки был в центре внимания недавнего опроса, проведенного командой Chrome . Результаты опроса выявили несколько областей, которые требуют дополнительной работы, чтобы сократить разрыв между библиотеками плагинов и CSS. Предстоящая работа будет сосредоточена на scroll-snap , в том числе:

  1. Доступность и совместимость API во всех браузерах.
  2. Работайте над новыми CSS API, такими как scroll-start .
  3. Работайте над новыми событиями JS, такими как snapChanged() .