Умная прокрутка со Scroll Snap Points

Содержание:
scroll-snap-type
scroll-snap-points-x, scroll-snap-points-y
scroll-snap-destination
scroll-snap-coordinate

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

Cпецификация: Scroll Snap Points.

Возьмем для примера такую галерею:

See the Pen Scroll Snap Points by yoksel (@yoksel) on CodePen.

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

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

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

Обычно проблема решается с помощью Js, но теперь есть решение на CSS.

Внимание: на момент написания статьи все следующие демо работают только в Firefox 39+.

Посмотрите на это демо в последнем Firefox:

See the Pen Scroll Snap Points by yoksel (@yoksel) on CodePen.

Попробуйте скроллить и увидите, что в этом примере картинки всегда аккуратно заполняют собой область просмотра. Как это сделано?

Для начала создадим галерею, для неё нужен совсем простой код.

HTML:

<div class="gallery">
    <img src="image.jpg" alt=""/>
    <img src="image.jpg" alt=""/>
    <img src="image.jpg" alt=""/>
    <img src="image.jpg" alt=""/>
    <img src="image.jpg" alt=""/>
</div>

CSS:


.gallery {
    width: 500px;
    height: 333px;
    overflow-y: hidden;
    overflow-x: auto;
    white-space: nowrap;
    }

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

Это был код галереи с обычной прокруткой, добавим немного магии:


.gallery {
    ...
    /* Scroll Snap Properties */
    scroll-snap-type: mandatory;
    scroll-snap-points-x: repeat(100%);
    }

Всего пара строчек кода, и галерея прокручивается по шагам, показывая только одну картинку в один момент времени. Красота!

Посмотрим на свойства, которые позволяют это сделать:

scroll-snap-type

Определяет насколько точно проматываемый контент должен выравниваться относительно родительского элемента. Задаётся контейнеру с прокруткой.

none — “прилипание” отключено, прокрутка ведет себя как обычно. Значение по умолчанию. mandatory — точное “прилипание”: при прокрутке элементы выравниваются точно по родителю. proximity — приблизительное “прилипание”: в зависимости от скорости проматывания элементы могут показываться по частям или выравниваться по родителю.

See the Pen Scroll Snap Points by yoksel (@yoksel) on CodePen.

See the Pen Scroll Snap Points by yoksel (@yoksel) on CodePen.

scroll-snap-points-x, scroll-snap-points-y

Определяет шаг скролла, задаётся контейнеру с прокруткой.

none — шаг не задан, содержимое прокручивается рывками. Значение по умолчанию. repeat(<length>) — определяет размер шага при прокрутке, значение может быть задано в процентах. scroll-snap-points-x: repeat(100%); означает, что длина шага равна ширине контейнера.

See the Pen Scroll Snap Points by yoksel (@yoksel) on CodePen.

scroll-snap-points-x: repeat(50%); в сочетании с scroll-snap-type: mandatory; ведет себя похоже на scroll-snap-type: proximity;: прокрутка получается нестрогой и при этом с управляемым размером шага.

See the Pen Scroll Snap Points by yoksel (@yoksel) on CodePen.

scroll-snap-destination

Определяет точку “прилипания” внутри контейнера с прокруткой. Первое значение задаёт координату по X, второе — по Y. Можно задавать в процентах. Задаётся контейнеру с прокруткой.

Значение по умолчанию: 0px 0px.

Обычно контент “прилипает” к левому краю, но при scroll-snap-destination: 100% 0; он будет прилипать к правому. Я увеличила ширину контейнера, чтобы было лучше видно.

See the Pen Scroll Snap Points by yoksel (@yoksel) on CodePen.

scroll-snap-coordinate

Определяет для прокручиваемых элементов координаты точки “прилипания”.

none — у элемента нет точки “прилипания”. Значение по умолчанию. <position> — задаёт точку “прилипания” относительно прокручиваемого элемента. Первое значение задаёт координату по X, второе — по Y. Можно задавать в процентах.

Удобная штука, если прокручиваемый контейнер больше содержащихся в нём элементов: благодаря сочетанию scroll-snap-coordinate: 50% 0; для дочерних элементов и scroll-snap-destination: 50% 0; для родителя прокручиваемые элементы всегда будут выравниваться точно по центру области прокрутки:

See the Pen Scroll Snap Points by yoksel (@yoksel) on CodePen.

При этом “прилипание” прекрасно работает для элементов разной ширины:

See the Pen Scroll Snap Points by yoksel (@yoksel) on CodePen.

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

К сожалению, умная прокрутка в данный момент поддерживается далеко не везде: полная поддержка есть только в Firefox 39+, также она частично поддерживается с префиксом -ms- в IE10+, а в Safari поддержка появится начиная со следующей версии.

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

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

Ссылки по теме:
CSS Scroll Snap Points
caniuse.com/#search=snap
Native CSS Scroll Snap Points
Если вы нашли ошибку или неточность, вы можете отредактировать статью с помощью prose.io, а также можно написать мне в комментариях или в Twitter.
Система комментирования от Disqus