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

Создавайте хорошо управляемые процессы прокрутки, указывая позиции привязки прокрутки.

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

Фон

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

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

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

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

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

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

CSS Scroll Snap

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

Для контейнера прокрутки можно включить привязку к оси прокрутки, используя свойство 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, которое можно использовать для регулировки эффективной видимой области контейнера прокрутки, или области привязки (snapport), используемой при расчете выравнивания привязки прокрутки. Это свойство определяет отступ относительно отступа контейнера прокрутки. В нашем примере был добавлен дополнительный отступ 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. Работайте над новыми событиями JavaScript, такими как snapChanged() .