Headroom.js — это лёгкая библиотека для управления поведением верхней панели при прокрутке страницы. Одной из важных задач при интеграции является управление фокусом элементов, особенно при динамическом скрытии и показе шапки, чтобы обеспечить доступность и корректное взаимодействие с пользователем.
Для начала Headroom подключается к DOM-элементу шапки следующим образом:
var header = document.querySelector("header");
var headroom = new Headroom(header, {
tolerance: {
up: 5,
down: 5
},
offset: 50,
classes: {
initial: "headroom",
pinned: "headroom--pinned",
unpinned: "headroom--unpinned"
}
});
headroom.init();
Ключевые моменты для фокус-менеджмента:
pinned — класс, который добавляется, когда шапка
видима.unpinned — класс, когда шапка скрыта.initial — исходное состояние до применения
анимации.Фокус-менеджмент часто зависит от этих классов, так как скрытая шапка может содержать элементы с интерактивными компонентами, такими как кнопки и ссылки. Необходимо гарантировать, что скрытые элементы не доступны через клавиатуру, чтобы избежать нарушения UX.
При добавлении Headroom.js важно синхронизировать
ARIA-атрибуты и tabindex с состояниями
шапки:
header.addEventListener("headroom:unpinned", function() {
const focusableElements = header.querySelectorAll("a, button, input, select, textarea");
focusableElements.forEach(el => {
el.setAttribute("tabindex", "-1");
});
});
header.addEventListener("headroom:pinned", function() {
const focusableElements = header.querySelectorAll("a, button, input, select, textarea");
focusableElements.forEach(el => {
el.removeAttribute("tabindex");
});
});
Пояснения:
tabindex="-1" исключает элемент из последовательности
табуляции.tabindex возвращает стандартное
поведение.headroom:unpinned и
headroom:pinned обеспечивает синхронизацию с анимацией
шапки.Для повышения доступности элементов шапки при изменении её состояния рекомендуется использовать ARIA-атрибуты:
header.setAttribute("aria-hidden", "false");
header.addEventListener("headroom:unpinned", function() {
header.setAttribute("aria-hidden", "true");
});
header.addEventListener("headroom:pinned", function() {
header.setAttribute("aria-hidden", "false");
});
Принципы:
aria-hidden="true" скрывает элемент от экранных
читалок.aria-hidden="false" делает его вновь доступным.tabindex предотвращает
попадание фокуса на скрытые элементы.В некоторых интерфейсах важно, чтобы при возвращении шапки пользовательский фокус автоматически устанавливался на ключевой элемент (например, на кнопку меню или логотип):
header.addEventListener("headroom:pinned", function() {
const mainButton = header.querySelector("button.menu-toggle");
if(mainButton) mainButton.focus();
});
Рекомендации:
pinned).Если содержимое шапки динамически изменяется (например, добавляются ссылки при авторизации пользователя), необходимо обновлять фокус-менеджмент после каждой модификации:
function updateFocusManagement() {
const focusableElements = header.querySelectorAll("a, button, input, select, textarea");
focusableElements.forEach(el => {
if(header.classList.contains("headroom--unpinned")) {
el.setAttribute("tabindex", "-1");
} else {
el.removeAttribute("tabindex");
}
});
}
// Вызов после изменения DOM
updateFocusManagement();
Это гарантирует, что новые элементы автоматически учитываются при управлении фокусом.
При интеграции с модальными окнами, сайдбарами или библиотеками типа FocusTrap необходимо учитывать, что Headroom.js может скрывать элементы, на которые установлены ограничения фокуса. Рекомендуется:
aria-hidden и
tabindex для поддержания последовательности навигации.focusin, focusout), чтобы избежать потери
фокуса при динамическом скрытии шапки.headroom:pinned и
headroom:unpinned, чтобы централизованно управлять
доступностью элементов.Этот подход обеспечивает полную совместимость Headroom.js с требованиями доступности, предотвращает случайное попадание фокуса на скрытые элементы и позволяет интегрировать шапку в сложные интерактивные интерфейсы.