Focus management

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


Прокрутка к элементу и установка фокуса

Smooth Scroll позволяет прокручивать страницу к определённому элементу через привязку к ссылкам с хешами (#id) или программно с помощью метода animateScroll. Однако простое смещение окна не меняет текущий фокус, что может вызвать проблемы для пользователей с клавиатурой или экранными читалками.

Пример базового использования:

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

// Программный вызов прокрутки
const target = document.querySelector('#section2');
scroll.animateScroll(target);

В этом примере элемент #section2 будет виден после анимации, но фокус останется на документе, а не на целевом элементе.


Автоматическая установка фокуса

Для правильного управления фокусом после завершения прокрутки следует использовать коллбэк after:

scroll.animateScroll(target, null, {
  speed: 600,
  offset: 0,
  updateURL: true,
  after: function(anchor, toggle) {
    anchor.setAttribute('tabindex', '-1'); // Делаем элемент фокусируемым, если это не интерактивный элемент
    anchor.focus({ preventScroll: true }); // Устанавливаем фокус без смещения страницы
  }
});

Ключевые моменты:

  • Атрибут tabindex="-1" позволяет программно установить фокус на элемент, который обычно не фокусируемый.
  • Опция preventScroll: true предотвращает повторное смещение страницы при установке фокуса.
  • Коллбэк after срабатывает после завершения анимации, что гарантирует корректное положение элемента на экране.

Обработка интерактивных элементов

Если целевой элемент уже интерактивен (например, button, input, a), дополнительный tabindex не нужен. В этом случае достаточно вызвать focus:

scroll.animateScroll(document.querySelector('#submitBtn'), null, {
  after: function(anchor) {
    anchor.focus();
  }
});

Это позволяет сохранить естественное поведение клавиатуры и корректно активировать элементы с точки зрения доступности.


Управление фокусом при навигации по хешам

Smooth Scroll может обновлять URL и автоматически обрабатывать ссылки с хешами. Для сохранения управления фокусом рекомендуется:

  1. Перехватывать стандартное событие клика по ссылке.
  2. Вызывать preventDefault() для предотвращения мгновенной прокрутки.
  3. Запускать анимацию Smooth Scroll с последующим управлением фокусом.

Пример:

document.querySelectorAll('a[href^="#"]').forEach(link => {
  link.addEventListener('click', function(e) {
    e.preventDefault();
    const target = document.querySelector(this.getAttribute('href'));
    scroll.animateScroll(target, this, {
      after: function(anchor) {
        anchor.setAttribute('tabindex', '-1');
        anchor.focus({ preventScroll: true });
      }
    });
  });
});

Фокус и динамически загружаемые элементы

Если контент на странице подгружается динамически, элемент может отсутствовать в DOM в момент инициализации Smooth Scroll. В этом случае нужно:

  • Проверять наличие элемента через document.querySelector.
  • Вызывать animateScroll только после полной загрузки контента.
  • Для элементов, добавленных после прокрутки, корректно устанавливать tabindex и фокус через коллбэк after.

Пример:

const dynamicTarget = document.querySelector('#dynamicSection');
if(dynamicTarget) {
  scroll.animateScroll(dynamicTarget, null, {
    after: (anchor) => {
      anchor.setAttribute('tabindex', '-1');
      anchor.focus({ preventScroll: true });
    }
  });
}

Поддержка доступности (ARIA)

Для элементов, на которые устанавливается фокус после прокрутки, важно соблюдать ARIA-рекомендации:

  • Если элемент является заголовком секции (h2, h3), добавление role="region" с aria-labelledby помогает экранным читалкам определить контекст.
  • Для интерактивных контейнеров использовать aria-live для уведомления о появлении нового контента после прокрутки.

Пример:

<section id="section2" role="region" aria-labelledby="section2-title">
  <h2 id="section2-title">Раздел 2</h2>
  ...
</section>
scroll.animateScroll(document.querySelector('#section2'), null, {
  after: (anchor) => {
    anchor.setAttribute('tabindex', '-1');
    anchor.focus({ preventScroll: true });
  }
});

Итоговая стратегия управления фокусом

  1. Всегда использовать коллбэк after для установки фокуса после завершения анимации.
  2. Добавлять tabindex="-1" для нефокусируемых элементов перед вызовом focus.
  3. Не изменять фокус интерактивных элементов, достаточно вызвать focus.
  4. Обрабатывать динамический контент и проверять существование элементов.
  5. Интегрировать ARIA-атрибуты для корректной работы со скринридерами.

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