Формы и их элементы

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

Элемент считается табируемым, если он удовлетворяет следующим условиям:

  • Является интерактивным по природе (<input>, <button>, <select>, <textarea>, <a href>).
  • Не имеет атрибута disabled.
  • Не скрыт с помощью display: none или visibility: hidden.
  • Не имеет tabindex="-1".

Библиотека предоставляет функции для поиска всех таких элементов, что позволяет строить динамические последовательности фокуса.


Установка и подключение

Для работы с библиотекой достаточно установить её через npm или yarn:

npm install tabbable
# или
yarn add tabbable

После установки подключение выполняется стандартным способом:

import { tabbable, isTabbable } from 'tabbable';
  • tabbable(node, options) — возвращает массив всех табируемых элементов внутри заданного узла node.
  • isTabbable(node, options) — проверяет, является ли конкретный элемент табируемым.

Опциональный объект options позволяет включать или исключать элементы, которые могут быть скрытыми, или управлять специфическими тегами.


Работа с формами и элементами ввода

Элементы формы традиционно считаются основными объектами для фокусировки. К ним относятся:

  • Текстовые поля (<input type="text">, <textarea>) — принимают текстовый ввод, могут быть табируемыми, если не заблокированы.
  • Кнопки (<button> и <input type="button|submit|reset">) — всегда участвуют в последовательности табуляции, если не отключены.
  • Ссылки (<a href="...">) — табируемы, если присутствует атрибут href.
  • Селекты (<select>) — табируемые по умолчанию, но могут быть исключены через tabindex.

Пример получения всех табируемых элементов формы:

const form = document.querySelector('#myForm');
const elements = tabbable(form);
console.log(elements); // Массив всех элементов, доступных для табуляции

Атрибут tabindex и управление фокусом

Атрибут tabindex играет ключевую роль в управлении табуляцией:

  • tabindex="0" — элемент участвует в естественной последовательности.
  • tabindex="-1" — элемент исключается из последовательности, но может быть сфокусирован программно (element.focus()).
  • tabindex="1" и выше — элемент получает приоритет выше естественных элементов, чем выше значение, тем раньше он получает фокус.

Пример приоритета элементов:

<input type="text" id="first" tabindex="2">
<input type="text" id="second" tabindex="1">
<button id="btn">Click me</button>

При нажатии Tab фокус перейдет: #second#firstbutton (естественный порядок).


Исключение элементов из последовательности

С помощью Tabbable легко исключить элементы, которые не должны быть доступными через клавишу Tab:

const allTabbable = tabbable(document.body);
const visibleTabbable = tabbable(document.body, { includeContainer: false });
  • includeContainer — если true, проверяется сам узел node, иначе только дочерние элементы.
  • getShadowRoot — позволяет обходить элементы в shadow DOM.

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


Обработка динамически изменяемых форм

Формы часто изменяются динамически: добавляются новые поля, кнопки или ссылки. Tabbable позволяет получать актуальный список элементов без ручного отслеживания изменений:

const updateTabbableList = () => {
  const tabbableElements = tabbable(document.querySelector('#dynamicForm'));
  console.log('Tabbable elements:', tabbableElements);
};

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


Проверка табируемости отдельных элементов

Функция isTabbable позволяет проверить конкретный элемент без обхода всех узлов:

const input = document.querySelector('#username');
if (isTabbable(input)) {
  console.log('Элемент можно табулировать');
} else {
  console.log('Элемент недоступен для Tab');
}

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


Интеграция с ARIA и доступностью

Tabbable хорошо работает в связке с атрибутами ARIA, обеспечивая корректный доступ для пользователей с ограниченными возможностями:

  • aria-hidden="true" — элемент будет игнорироваться при табуляции.
  • role="dialog" и aria-modal="true" — при создании модальных окон последовательность фокуса может быть ограничена только содержимым модалки.

Сочетание Tabbable и ARIA обеспечивает полностью предсказуемое управление фокусом, что критично для доступности.


Особенности взаимодействия с shadow DOM и фреймами

Tabbable умеет работать с современными компонентами:

  • Для shadow DOM можно использовать getShadowRoot и рекурсивно обходить элементы.
  • В iFrame элементы доступны через contentDocument и стандартный вызов tabbable(frame.contentDocument).

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


Практические рекомендации

  1. Всегда использовать Tabbable для динамических форм, чтобы избежать «потерянного фокуса».
  2. Использовать tabindex осознанно, не превышая значения > 10, чтобы не нарушать естественный порядок.
  3. Обходить shadow DOM и фреймы, если интерфейс состоит из кастомных компонентов.
  4. Комбинировать с ARIA, особенно для модальных окон и сложных форм.
  5. Проверять tab-индекс при создании динамических элементов, чтобы новые поля были корректно включены в последовательность.

Использование Tabbable позволяет управлять фокусировкой форм на детальном уровне, улучшает доступность и предотвращает ошибки, связанные с недоступными элементами или неожиданной последовательностью Tab.