Как сделать скролл в css

Практика использования спецификации CSS Scroll Snap

Часто ли у вас возникало желание воспользоваться какой-нибудь возможностью CSS, позволяющей, без лишних усилий, создать элемент-контейнер, поддерживающий прокрутку? CSS, что очень хорошо, даёт нам такую возможность. Я, когда только начинал заниматься фронтенд-разработкой, пользовался для создания прокручиваемых элементов JavaScript-плагинами. Но иногда нужно что-то такое, что позволяет создавать подобные элементы просто и быстро, без привлечения JavaScript. Сделать это можно, воспользовавшись спецификацией CSS Scroll Snap.

Здесь я хочу раскрыть основы практического использования этой спецификации. Я сам только недавно разобрался с CSS Scroll Snap, поэтому рассказывать всё это буду, так сказать, «по горячим следам».

Зачем использовать CSS Scroll Snap?

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

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

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

Основы работы с контейнерами, поддерживающими прокрутку

Для того чтобы создать элемент-контейнер, поддерживающий прокрутку, понадобится следующее:

  • Использование свойства из группы свойств overflow со значением, отличающимся от visible .
  • Применение некоего способа вывода элементов в контейнере, позволяющего расположить их рядом друг с другом (inline-элементы).

Популярным CSS-решением для размещения элементов в контейнере многие годы было свойство white-space: nowrap . В наши дни без этого, к счастью, можно обойтись, воспользовавшись свойством display: flex :

Контейнер, поддерживающий прокрутку элементов

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

Проблема контейнеров, поддерживающих прокрутку содержимого

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

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

Работа с обычным контейнером, поддерживающим прокрутку

Как видите, каждый элемент приходится буквально «вести» на его место, не отрывая палец от экрана. Это — не «свайп» и это очень неудобно с точки зрения пользователя. Но, используя возможности CSS Scroll Snap, мы можем решить эту проблему, просто описав точки привязки (snap point), которые упростят горизонтальную или вертикальную прокрутку содержимого страницы.

Знакомство с CSS Scroll Snap

Для того чтобы воспользоваться возможностями CSS Scroll Snap дочерние элементы должны выводиться внутри контейнера в inline-режиме. Сделать это можно с использованием одного из вышеописанных методов. Я использую для этих целей Flexbox-макет.

Теперь нам, чтобы спецификация CSS Scroll Snap заработала бы, нужно воспользоваться ещё парой свойств. Главный вопрос тут заключается в том, куда именно их нужно добавить.

Сначала надо добавить свойство scroll-snap-type к контейнеру, поддерживающему прокрутку. В нашем примере это — элемент с классом section . Затем нужно добавить свойство scroll-snap-align к дочерним элементам (класс section__item ).

Вы, вероятно, видя кучу новых ключевых слов, вроде x mandatory и start , чувствуете сейчас некоторую растерянность. Но ничего страшного тут нет — скоро вы с ними разберётесь.

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

Вот как это выглядит.

Элементы привязаны к началу контейнера

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

▍Свойство scroll-snap-type

Свойство scroll-snap-type , в соответствии со спецификацией, позволяет указать на то, что элемент является snap-контейнером. Его значения позволяют задать то, насколько жёстко осуществляется привязка содержимого этого контейнера при прокрутке, а так же то, прокрутка по каким осям принимается во внимание.

▍Оси контейнера

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

Горизонтальная прокрутка и вертикальная прокрутка

▍Настройка жёсткости привязки

Мы, настраивая контейнер, можем задать не только направление прокрутки, но и то, насколько жёстко содержимое должно быть связано с точками привязки. Сделать это можно с помощью значений mandatory и proximity свойства scroll-snap-type .

Ключевое слово mandatory означает, что браузер обязательно должен привязать элемент к точке привязки. Представим, что свойство scroll-snap-align установлено в значение start . Это означает, что элементы при прокрутке обязательно должны ориентироваться на начало контейнера.

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

Элементы жёстко привязаны к началу контейнера

Здесь можно найти видео к этому примеру.

Прокрутка с привязкой

А вот — интерактивный вариант этого примера.

Работа с интерактивным вариантом примера

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

А вот если тут используется значение proximity , то элементы будут вести себя уже немного свободнее, привязка работает не так жёстко. Обратите внимание на то, что значение proximity используется в свойстве scroll-snap-type по умолчанию. Я показываю тут последствия его явного применения лишь ради того, чтобы сделать изложение понятнее.

Элементы привязаны к началу контейнера менее жёстко

Последствия использования значения proximity

▍Свойство scroll-snap-align

При настройке дочерних элементов контейнера, поддерживающего прокрутку, нужно указать то, к какому месту контейнера привязываются эти элементы. Делается это путём настройки свойства scroll-snap-align , которое поддерживает значения start (начало), center (центр) и end (конец).

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

Значения свойства scroll-snap-align и их влияние на содержимое, расположенное в контейнере по горизонтали

Если содержимое в контейнере ориентировано вертикально, это значит, что точки привязки, задаваемые значениями start , center и end , тоже расположены по вертикали.

Значения свойства scroll-snap-align и их влияние на содержимое, расположенное в контейнере по вертикали

Ниже приведено несколько видеопримеров.

▍Привязка содержимого к началу контейнера

При установке свойства scroll-snap-align в значение start содержимое контейнера привязывается к его началу.

Привязка содержимого к началу контейнера

▍Привязка содержимого к центру контейнера

При установке свойства scroll-snap-align в значение center содержимое контейнера привязывается к его центру.

Привязка содержимого к центру контейнера

▍Привязка содержимого к концу контейнера

При установке свойства scroll-snap-align в значение end содержимое контейнера привязывается к его концу.

Привязка содержимого к концу контейнера

▍Использование свойства scroll-snap-stop

Иногда нужно сделать так, чтобы пользователь, прокручивающий список элементов, не пропустил бы случайно какой-нибудь очень важный элемент. Если список прокручивают слишком быстро, то нечто подобное вполне может случиться. Решить вышеописанную задачу можно, прибегнув к свойству scroll-snap-stop .

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

При слишком быстрой прокрутке некоторые элементы можно пропустить

По умолчанию свойство scroll-snap-stop установлено в значение normal . Для принудительной привязки элементов это свойство можно установить в значение always . Благодаря этому браузер будет останавливать прокрутку каждый раз, когда очередной элемент достигает точки привязки.

Вот соответствующие стили:

Браузер не позволяет пропускать элементы

В результате пользователь, выполнив одно движение, может прокрутить список лишь на один элемент. Благодаря этому можно предотвратить пропуск важных элементов. При таком подходе каждая точка привязки будет напоминать знак «STOP».

Точки привязки — это, при использовании значения always, то же самое, что и знаки «STOP»

Здесь можно найти интерактивный пример, позволяющий поэкспериментировать со свойством scroll-snap-stop .

Эксперименты со свойством scroll-snap-stop

▍Внутренние отступы и свойство scroll-padding

Сокращённое свойство scroll-padding позволяет устанавливать внутренние отступы, воздействующие на прокрутку содержимого в контейнере. Оно похоже на обычное свойство padding . На следующем рисунке показаны последствия создания внутреннего левого отступа шириной в 50px . Благодаря этому дочерние элементы будут привязаны к точке, отстоящей от края контейнера на 50 пикселей.

Вот стили, соответствующие сценарию горизонтальной прокрутки:

Использование свойства scroll-padding при реализации горизонтальной прокрутки

То же самое применимо и к контейнерам с вертикальной прокруткой:

Использование свойства scroll-padding при реализации вертикальной прокрутки

▍Внешние отступы и свойство scroll-margin

Сокращённое свойство scroll-margin позволяет настраивать внешние отступы дочерних элементов контейнера, учитываемые при их прокрутке. Например, как показано на следующем рисунке, добавив к элементу .item-2 свойство scroll-margin-left: 20px , мы можем сместить позицию привязки элемента на 20 пикселей.

Использование свойства scroll-margin

В результате прокрутка остановится в тот момент, когда до края контейнера будет 20 пикселей. А если пользователь продолжит прокручивать список и дойдёт до элемента .item-3 , то край этого элемента будет привязан к началу контейнера, так как для этого элемента свойство scroll-margin не задано.

Способы использования CSS Scroll Snap

▍Список изображений

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

Прокручиваемый список изображений

Обратите внимание на то, что в качестве значения свойства scroll-snap-type используется x . Жёсткость привязки будет, по умолчанию, установлена в значение proximity .

Вот интерактивный вариант этого примера.

Эксперименты со списком изображений

▍Список друзей

Список друзей — это ещё один отличный способ использования CSS Scroll Snap. Нижеприведённый пример взят с Facebook (то есть — перед нами — реальный пример).

Список друзей

Вот CSS-код к этому примеру:

Обратите внимание на то, что при настройке контейнера используется свойство padding-bottom: 32px . Сделано это для того чтобы дать дополнительное пространство для вывода тени, задаваемой свойством box-shadow .

Без использования свойства padding-bottom тень выводится не полностью

▍Список аватаров

В данном примере нас интересует значение center , задаваемое свойству scroll-snap-align дочерних элементов контейнера.

Список аватаров

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

Здесь с этим примером можно поэкспериментировать.

Эксперименты со списком аватаров

▍Список разделов, занимающих всю доступную высоту области просмотра страницы

Использование спецификации CSS Scroll Snap может пригодиться и при реализации сценариев вертикальной прокрутки элементов. Например — при организации работы с элементами, занимающими всю высоту области просмотра страницы.

Элементы, занимающие всю высоту области просмотра страницы

Вот разметка к этому примеру:

Здесь можно найти рабочий вариант этого примера.

Элементы, занимающие всю доступную высоту области просмотра страницы

▍Значения inline и block свойства scroll-snap-type

Полагаю, стоит сказать о том, что при настройке свойства scroll-snap-type можно использовать логические CSS-значения inline и block . Вот пример:

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

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

▍Доступность

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

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

Пользовательские полосы прокрутки в CSS

Пользовательские полосы прокрутки в CSS

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

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

Пользовательские полосы прокрутки в CSS

Вступление

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

Пользовательские полосы прокрутки в CSS

Практический курс по верстке адаптивного сайта с нуля!

Изучите курс и узнайте, как верстать современные сайты на HTML5 и CSS3

Дорожка — это основа полосы прокрутки, а ползунок — это то, что пользователь перетаскивает для прокрутки страницы или раздела.

Следует иметь в виду одну важную вещь: полоса прокрутки может работать горизонтально или вертикально, в зависимости от дизайна. Кроме того, она может измениться при работе с многоязычным веб-сайтом, который работает как слева направо (LTR), так и справа налево (RTL).

Пользовательские полосы прокрутки в CSS

Настройка дизайна долосы прокрутки

Раньше пользовательская полоса прокрутки использовалась только для webkit, поэтому, она не использовались в Firefox и IE. Сейчас, у нас есть новый синтаксис, который работает только в Firefox и упростит нам жизнь, когда он будет полностью поддерживаться. Я пройдусь по старому синтаксису Webkit, а затем по новому.

Старый синтаксис

Ширина полосы прокрутки

Во-первых, нам нужно определить размер полосы прокрутки. Это может быть ширина вертикальных полос прокрутки и высота горизонтальных.

Способы добавления плавной прокрутки страницы в CSS и JavaScript

Наверняка вы посещали страницы, которые плавно прокручивают контент при клике на ссылке к соответствующему блоку. Это красиво выглядит на лэндингах (LandingPage, или посадочная страница), в которых пространство страницы разбито на части, или в больших статьях с содержанием. Такая прокрутка называется скроллингом (от англ. scroll).

Однако, это не только красиво, но и достаточно просто с точки зрения реализации.

Прокрутка страницы с помощью CSS

Для того чтобы плавная прокрутка происходила на всей странице, необходимо добавить свойство scroll-behavior: smooth для селектора html .

Если плавная прокрутка необходима в пределах какого-то контейнера, то это свойство назначают для него.

По умолчанию свойство scroll-behavior имеет значение auto , т.е. прокрутка будет обычной, без эффекта плавности.
Посмотрите пример, основанный на css-свойстве (открыть в новой вкладке):

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

Ложкой дегтя для этого свойства будет неполная поддержка его браузерами. Вы можете посмотреть, какова она на скриншоте и на caniuse.com.

Поддержка свойства scroll-behavor браузерами

Поддержка свойства scroll-behavor браузерами

Поэтому рассмотрим, как сделать плавную прокрутку с помощью jQuery и JavaScript.

Скроллинг с помощью jQuery

Понятно, что для использования jQuery вам нужно будет сначала подключить эту библиотеку. Дальше нужно будет отслеживать клики по ссылкам, у которых есть хэш ( # ) и анимировать свойство scrollTop для селектора $(‘html, body’) .

Сам код будет небольшим:

Это решение является кроссбраузерным, хотя у него есть один недостаток — если на вашем сайте jQuery не используется для работы с другими объектами/плагинами, то подключать лишние 88кб или порядка 40кб в gzip-сжатом виде не очень интересно ради 10-15 строк кода.
Пример (открыть в новой вкладке):

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

Здесь тоже есть 3 решения, каждое из которых использует свой подход к созданию плавности прокрутки с помощью разных JS-методов.

Решение 1. Метод scrollIntoView()

Из документации на MDN узнаем, что

Метод Element.scrollIntoView() прокручивает текущий контейнер родителя элемента, так, чтобы этот элемент, на котором был вызван scrollIntoView() был видим пользователю.

Этот метод имеет параметры, подобные css-свойству scroll-behavior: smooth для прокрутки контента к элементу с нужным id, указанным в виде хэш в ссылке.

К сожалению, и тут не обошлось без "ложки дегтя" в виде поддержки браузеров. Давайте обратимся к caniuse.com и увидим такую картину:

Поддержка свойства scrollIntoView браузерами

Поддержка свойства scrollIntoView браузерами

К сожалению, нужное нам значение свойства behavior: ‘smooth’ поддерживается не всеми браузерами.

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

Пример прокрутки контента с помощью метода scrollIntoView() (открыть в новой вкладке)).

Решение 2. Используем window.scrollBy() для плавной прокрутки.

Тут все методы и свойства и имеют хорошую поддержку браузерами.

Код JavaScript предполагает, что на вашей странице нет абсолютно позиционированной или фиксированной шапки сайта (элемент <header> ), в котором чаще всего размещаются ссылки-якоря на разделы страницы, поэтому переменная offsetTop (смещение сверху) сначала задана как 0.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *