Библиотека ally.js предназначена для упрощения работы с доступностью веб-приложений, в частности с управлением фокуса и навигацией с клавиатуры. Ключевой аспект этой работы — корректное определение фокусируемых элементов, то есть тех элементов, на которые пользователь может переместить фокус с помощью клавиши Tab или программно через JavaScript.
Фокусируемый элемент — это элемент DOM, который может получать фокус. В HTML к таким элементам традиционно относятся:
<input>,
<textarea>, <select>,
<button>hreftabindex >= 0Однако для реального интерфейса важны дополнительные условия, влияющие на фокусируемость:
display не
none, visibility не hidden)disabled)Библиотека ally.js учитывает все эти условия и предоставляет API для корректного выявления таких элементов.
query.tabstoppable()Метод tabstoppable возвращает массив элементов, которые могут быть достигнуты с помощью клавиши Tab. Особенности:
tabindex и последовательность
фокусаПример использования:
import * as ally from 'ally.js';
const tabbableElements = ally.query.tabstoppable({ context: document.body });
tabbableElements.forEach(el => {
console.log(el, el.tabIndex);
});
Параметр context позволяет ограничить область поиска
конкретным контейнером, что полезно для модальных окон или динамических
компонентов.
is.tabstop(element)Метод is.tabstop проверяет, является ли конкретный элемент фокусируемым через Tab. Возвращает булево значение:
const button = document.querySelector('#submitBtn');
if (ally.is.tabstop(button)) {
console.log('Элемент доступен для фокуса');
}
Эта проверка учитывает:
is.focusable(element)Метод is.focusable шире, чем
is.tabstop. Он проверяет возможность программного фокуса
через element.focus(), вне зависимости от
tabindex. Используется для анализа элементов интерфейса,
которые могут быть сфокусированы скриптами, но недоступны через Tab:
const div = document.querySelector('.custom-div');
if (ally.is.focusable(div)) {
div.focus();
}
tabindextabindex="0" добавляются в естественный
порядок фокусировкиtabindex получают приоритет в
порядке увеличения значенияtabindex="-1" становятся программно
фокусируемыми, но не доступны через Tabally.js автоматически учитывает эти правила при расчёте фокусируемых элементов.
В интерфейсах с динамическим контентом (списки, модальные окна, аккордеоны) важно пересчитывать фокусируемые элементы после изменений DOM. ally.js предоставляет функции для:
Пример:
const modal = document.querySelector('#myModal');
const focusableInModal = ally.query.tabstoppable({ context: modal });
Это позволяет реализовать циклический фокус внутри модальных окон и предотвращает уход фокуса за пределы контейнера.
const tabbable = ally.query.tabstoppable({ context: document.body });
tabbable.forEach(el => console.log(el.tagName, el.tabIndex));
const element = document.querySelector('.custom-element');
if (ally.is.focusable(element)) {
element.focus();
}
const modal = document.querySelector('#modal');
const focusableElements = ally.query.tabstoppable({ context: modal });
focusableElements[0].focus(); // устанавливаем фокус на первый элемент
tabindex.is.tabstop и
is.focusable различают доступность через Tab и программный
фокус.context позволяют гибко работать с модальными окнами и
компонентами, обновляемыми через JavaScript.Эта библиотека позволяет строить доступные и предсказуемые интерфейсы, где контроль над фокусом становится простым и надёжным инструментом.