Библиотека ally.js предоставляет комплексный набор инструментов для работы с доступностью веб-приложений, включая управление фокусом, определение видимых элементов и создание удобной клавиатурной навигации. В контексте навигации по вариантам, основное внимание уделяется управлению фокусом, предотвращению «залипания» клавиатурного взаимодействия и поддержке ARIA-атрибутов.
Ключевой принцип: каждый интерактивный элемент должен быть доступен через клавиатуру, а порядок навигации должен соответствовать логике пользовательского интерфейса.
Для работы с клавиатурной навигацией ally.js предоставляет метод
tabOrder. Он позволяет определить последовательность обхода
фокуса по DOM-элементам:
const tabSequence = ally.query.tabOrder({
context: document.getElementById('options-container')
});
tabSequence.forEach(element => {
element.addEventListener('focus', () => {
console.log('Фокус установлен на элемент:', element);
});
});
Ключевые моменты:
context определяет область, в которой будет вычисляться
порядок табуляции.Ally.js предоставляет несколько функций для точного управления фокусом:
focusable – определяет, какие элементы
могут получать фокус.focus – программно устанавливает фокус
на конкретный элемент.nextFocus / previousFocus
– позволяет переходить к следующему или предыдущему фокусируемому
элементу с учётом видимости и доступности.Пример установки фокуса на первый видимый вариант:
const options = ally.query.focusable({
context: document.getElementById('options-container')
});
if (options.length) {
ally.focus.focus(options[0]);
}
Особенности:
display: none,
visibility: hidden и aria-hidden="true".Навигация по вариантам часто требует использования стрелок клавиатуры (Arrow Up, Arrow Down, Arrow Left, Arrow Right). Ally.js не предоставляет готовых обработчиков для конкретных клавиш, но облегчает работу с фокусом, что позволяет реализовать следующую схему:
const optionsContainer = document.getElementById('options-container');
const options = Array.from(ally.query.focusable({ context: optionsContainer }));
optionsContainer.addEventListener('keydown', (event) => {
const currentIndex = options.indexOf(document.activeElement);
switch(event.key) {
case 'ArrowDown':
const nextIndex = (currentIndex + 1) % options.length;
ally.focus.focus(options[nextIndex]);
event.preventDefault();
break;
case 'ArrowUp':
const prevIndex = (currentIndex - 1 + options.length) % options.length;
ally.focus.focus(options[prevIndex]);
event.preventDefault();
break;
}
});
Принципы реализации:
event.preventDefault() предотвращает стандартное
поведение браузера.Для компонентов с вариантами (например,
<ul role="listbox"> или
<div role="radiogroup">) важно синхронизировать фокус
с ARIA-состояниями:
aria-selected для активного варианта.aria-activedescendant для контейнера, когда фокус
перемещается программно.Пример обновления состояния при смене фокуса:
options.forEach((option) => {
option.addEventListener('focus', () => {
options.forEach(o => o.setAttribute('aria-selected', 'false'));
option.setAttribute('aria-selected', 'true');
optionsContainer.setAttribute('aria-activedescendant', option.id);
});
});
Вывод: совместное использование ally.js и ARIA обеспечивает корректное восприятие навигации скринридерами и другими вспомогательными технологиями.
В интерфейсах с изменяемым набором вариантов необходимо обновлять список фокусируемых элементов:
function refreshOptions() {
return ally.query.focusable({ context: optionsContainer });
}
let currentOptions = refreshOptions();
optionsContainer.addEventListener('DOMNodeInserted', () => {
currentOptions = refreshOptions();
});
optionsContainer.addEventListener('DOMNodeRemoved', () => {
currentOptions = refreshOptions();
});
Особенности:
tabbable – возвращает элементы,
которые реально доступны через клавишу Tab, исключая элементы с
tabindex="-1".is.focused – проверяет, находится ли
элемент в фокусе, полезно для условных переходов.nextTabbable /
previousTabbable – позволяет реализовать кастомные
циклические или направленные переходы по фокусируемым элементам.Эти функции упрощают построение сложных интерфейсов с вариантами, обеспечивая предсказуемую и доступную клавиатурную навигацию.
Клавиатурная навигация по вариантам с использованием ally.js сочетает в себе программное управление фокусом, фильтрацию невидимых элементов, интеграцию с ARIA и возможность динамического обновления интерфейса. Такой подход позволяет создавать доступные и интуитивно понятные компоненты, соответствующие стандартам WCAG и рекомендациям по доступности веб-контента.