Определение фокусируемых элементов

Библиотека ally.js предназначена для упрощения работы с доступностью веб-приложений, в частности с управлением фокуса и навигацией с клавиатуры. Ключевой аспект этой работы — корректное определение фокусируемых элементов, то есть тех элементов, на которые пользователь может переместить фокус с помощью клавиши Tab или программно через JavaScript.

Основные понятия фокусируемости

Фокусируемый элемент — это элемент DOM, который может получать фокус. В HTML к таким элементам традиционно относятся:

  • Элементы форм: <input>, <textarea>, <select>, <button>
  • Ссылки с атрибутом href
  • Элементы с tabindex >= 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('Элемент доступен для фокуса');
}

Эта проверка учитывает:

  • Встроенные правила HTML
  • Видимость и активность элемента
  • Настройки CSS, влияющие на фокусируемость

is.focusable(element)

Метод is.focusable шире, чем is.tabstop. Он проверяет возможность программного фокуса через element.focus(), вне зависимости от tabindex. Используется для анализа элементов интерфейса, которые могут быть сфокусированы скриптами, но недоступны через Tab:

const div = document.querySelector('.custom-div');
if (ally.is.focusable(div)) {
    div.focus();
}

Важные нюансы при работе с tabindex

  • Элементы с tabindex="0" добавляются в естественный порядок фокусировки
  • Элементы с положительным tabindex получают приоритет в порядке увеличения значения
  • Элементы с tabindex="-1" становятся программно фокусируемыми, но не доступны через Tab

ally.js автоматически учитывает эти правила при расчёте фокусируемых элементов.

Работа с динамическими элементами

В интерфейсах с динамическим контентом (списки, модальные окна, аккордеоны) важно пересчитывать фокусируемые элементы после изменений DOM. ally.js предоставляет функции для:

  • Пересчёта элементов в определённом контейнере
  • Фильтрации элементов по условию доступности

Пример:

const modal = document.querySelector('#myModal');
const focusableInModal = ally.query.tabstoppable({ context: modal });

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

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

  1. Получение всех элементов, доступных через Tab:
const tabbable = ally.query.tabstoppable({ context: document.body });
tabbable.forEach(el => console.log(el.tagName, el.tabIndex));
  1. Проверка возможности программного фокуса:
const element = document.querySelector('.custom-element');
if (ally.is.focusable(element)) {
    element.focus();
}
  1. Управление фокусом в модальном окне:
const modal = document.querySelector('#modal');
const focusableElements = ally.query.tabstoppable({ context: modal });
focusableElements[0].focus(); // устанавливаем фокус на первый элемент

Выводы о подходе ally.js

  • Комплексный анализ DOM: ally.js учитывает видимость, активность и правила tabindex.
  • Разделение логики: методы is.tabstop и is.focusable различают доступность через Tab и программный фокус.
  • Удобство динамического интерфейса: фильтры по context позволяют гибко работать с модальными окнами и компонентами, обновляемыми через JavaScript.
  • Полная совместимость: поддержка современных браузеров и корректная работа с CSS, влияющим на фокус.

Эта библиотека позволяет строить доступные и предсказуемые интерфейсы, где контроль над фокусом становится простым и надёжным инструментом.