Фиксированный заголовок с выделенными разделами при прокрутке

Фиксированный заголовок с выделенными разделами при прокрутке

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

Раньше до добавления CSS position: sticky реализация фиксированного заголовка была огромной болью. Поддержка некоторых сценариев (таких как заголовки таблиц и т. д.) была на низком уровне, но вы можете узнать больше об этом на веб-сайте caniuse.

Настройка

Это будет структура, с которой мы будем работать. Некоторые вещи, которые стоит упомянуть — это top-spacer и bottom-spacer, просто произвольные высоты. Это позволяет нам иметь пространство для прокрутки сверху и достаточно места, чтобы прокручивать раздел контента полностью.

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

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

Узнать подробнее

В нашем заголовке используются flexbox и отображаются кнопки, которые можно будет нажимать для прокрутки к различным разделам. Каждый из наших разделов будет составлять 40vh или 40% от высоты окна просмотра, и мы зададим для каждого свой цвет.

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

Сделаем заголовок фиксированным

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

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

Фиксированный заголовок с выделенными разделами при прокрутке

Клик для прокрутки

Браузер также реализует возможность прокрутки к различным элементам, вы можете вызвать element.scrollIntoView() или элемент scrollTo для прокрутки до определенного смещения.

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

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

Фиксированный заголовок с выделенными разделами при прокрутке

Прокрутка в пределах монитора

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

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

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

Измерение высоты и смещения

Мы будем использовать хук useRef, который позволит получить доступ к элементу DOM каждого раздела, чтобы мы могли получить высоту / смещение. Таким образом, у нас есть значение для ссылки на будущее, мы можем поместить их в массив, поэтому, когда мы обнаруживаем что-то имеющее отношение к нашему ref, у нас есть способ определить, о чем идет речь.

Теперь мы прикрепляем их к разделам.

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

Концепция заключается в том, чтобы получить scrollY (на сколько пользователь прокрутил страницу). Затем мы можем увидеть, находится ли это значение между верхом / низом элемента.

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

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

Узнать подробнее

Мы используем getBoundingClientRect(), чтобы получить height элемента. Тогда offsetTop будет верхней позицией в пикселях. Внизу будет offsetTop + height элемента.

Выделение раздела при прокрутке

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

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

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

Прикрепляем ref.

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

Затем мы можем просмотреть каждый из разделов и получить функцию offsetTop и offsetBottom с помощью getDimensions. Теперь мы можем проверить scrollPosition, больше ли значение вершины элемента. Прокрутил ли пользователь страницу хотя бы немного. Затем мы также проверяем scrollPosition.

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

Мы используем find при поиске нужного элемента, и это также скажет нам, когда мы вообще не находимся в разделе.

Стоит отметить, что, поскольку мы зависим от предыдущего visibleSection, нам нужно добавить его в зависимости useEffect. Когда раздел изменится, он запустит очистку, удалит прослушиватель прокрутки окна и затем снова запустит эффект.

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

Фиксированный заголовок с выделенными разделами при прокрутке

Удаление предыдущего выделения

Еще один момент, о котором нам нужно позаботиться — когда пользователь прокручивает контент вниз, а затем прокручивает обратно в начало страницы. Если мы добавим else if и обнаружим, что мы не нашли раздел selected. Это означает, что мы вообще не находимся ни в одном разделе. Затем мы проверяем, есть ли у нас выбранный раздел, и удаляем выделение, установив для visibleSection значение undefined.

Восстановление позиции прокрутки

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

Заключение

Это все. Если вы просто хотели закрепить заголовок и вам не нужно знать, какой раздел вы сейчас просматриваете, вы могли бы просто добавить position: sticky. Но возможность нажимать кнопки для прокрутки к разделам и выделение раздела, в котором находится пользователь, обеспечивает более приятный опыт.

Фиксированный заголовок с выделенными разделами при прокрутке

Автор: Jason Brown

Источник: https://codeburst.io

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

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

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

Узнать подробнее

PSD to HTML

Практика верстки сайта на CSS Grid с нуля

Смотреть

Метки:

Похожие статьи:

Комментарии Вконтакте:

Комментарии Facebook:

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