Автоматическое выделение пунктов

Автоматическое выделение пунктов (active state) в интерфейсах с прокруткой является важной функциональностью для улучшения навигации. В контексте Smooth Scroll в JavaScript оно позволяет отслеживать текущий видимый раздел страницы и подсвечивать соответствующую ссылку в меню, обеспечивая пользователю визуальный ориентир.


Подключение и настройка Smooth Scroll

Для начала необходимо подключить библиотеку Smooth Scroll. Обычно используется CDN или установка через npm/yarn:

<script src="https://cdn.jsdelivr.net/npm/smooth-scroll@16/dist/smooth-scroll.polyfills.min.js"></script>

Инициализация происходит следующим образом:

const scroll = new SmoothScroll('a[href*="#"]', {
  speed: 500,
  offset: 0,
  updateURL: false
});

Параметры speed и offset позволяют регулировать скорость прокрутки и смещение относительно верха окна. Параметр updateURL отключает изменение адресной строки при прокрутке.


Определение целевых секций и пунктов меню

Для корректного отслеживания активного пункта необходимо:

  1. Задать уникальные идентификаторы для каждой секции контента:
<section id="section1">...</section>
<section id="section2">...</section>
<section id="section3">...</section>
  1. Создать меню с ссылками на эти секции:
<nav>
  <a href="#section1">Раздел 1</a>
  <a href="#section2">Раздел 2</a>
  <a href="#section3">Раздел 3</a>
</nav>

Каждая ссылка должна соответствовать идентификатору секции через атрибут href="#id".


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

Для определения текущей секции используется событие scroll. Необходимо получить координаты каждой секции относительно верхней части документа:

const sections = document.querySelectorAll('section');
const menuLinks = document.querySelectorAll('nav a');

window.addEventListener('scroll', () => {
  let scrollPos = window.scrollY || window.pageYOffset;

  sections.forEach((section, index) => {
    if (
      scrollPos >= section.offsetTop - 50 &&
      scrollPos < section.offsetTop + section.offsetHeight - 50
    ) {
      menuLinks.forEach(link => link.classList.remove('active'));
      menuLinks[index].classList.add('active');
    }
  });
});
  • scrollPos определяет текущую вертикальную позицию прокрутки.
  • Смещение -50 учитывает высоту фиксированного меню или визуальные особенности интерфейса.
  • Метод classList.add('active') выделяет текущую ссылку, а classList.remove('active') убирает подсветку с остальных.

Оптимизация производительности

При большом количестве секций или сложной верстке обработка события scroll может вызывать задержки. Для оптимизации используют throttle или debounce:

function throttle(fn, wait) {
  let time = Date.now();
  return function () {
    if (time + wait - Date.now() < 0) {
      fn();
      time = Date.now();
    }
  };
}

window.addEventListener('scroll', throttle(() => {
  // логика подсветки
}, 100));

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


Учёт динамического контента

Если секции загружаются асинхронно или изменяются по высоте, необходимо обновлять массив sections перед каждой проверкой:

function updateSections() {
  return document.querySelectorAll('section');
}

window.addEventListener('resize', () => {
  sections = updateSections();
});

Это предотвращает ошибки подсветки при изменении размеров элементов или добавлении новых секций.


Плавная интеграция с Smooth Scroll

Smooth Scroll предоставляет коллбэки, которые можно использовать для синхронизации активного состояния с завершением анимации прокрутки:

const scroll = new SmoothScroll('a[href*="#"]', {
  speed: 500,
  offset: 0,
  updateURL: false,
  after: function (anchor, toggle) {
    menuLinks.forEach(link => link.classList.remove('active'));
    toggle.classList.add('active');
  }
});
  • after вызывается после завершения прокрутки к выбранной секции.
  • toggle — ссылка, по которой была выполнена прокрутка.
  • Такой подход исключает рассинхронизацию между прокруткой и выделением пунктов меню.

Поддержка адаптивного интерфейса

Для мобильных устройств и интерфейсов с динамическими меню важно учитывать следующие моменты:

  • Высота фиксированных шапок (offset) должна корректироваться при изменении размеров окна.
  • Активная ссылка должна быть видимой в скролле меню, если оно горизонтальное:
document.querySelector('.active').scrollIntoView({
  beh * avior: 'smooth',
  inline: 'center'
});
  • При быстром скролле вручную подсветка должна оставаться синхронизированной с текущей позицией.

Кастомизация стилей активного пункта

CSS позволяет гибко оформлять активный пункт:

nav a.active {
  color: #ff6600;
  font-weight: bold;
  border-bottom: 2px solid #ff6600;
}

Использование transition добавляет плавность:

nav a {
  transition: color 0.3s, border-bottom 0.3s;
}

Итоговый подход

Комбинация отслеживания прокрутки, оптимизации через throttle, учета динамических изменений и интеграции с Smooth Scroll обеспечивает:

  • Надёжное подсвечивание текущего пункта меню.
  • Плавную анимацию при навигации.
  • Совместимость с различными устройствами и изменяющимся контентом.
  • Минимальную нагрузку на производительность.

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