Невалидные контейнеры

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

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

Tabbable анализирует DOM и возвращает массив элементов, которые считаются фокусируемыми. Ключевое различие — не все элементы с атрибутом tabindex автоматически считаются доступными для фокуса. На фокус влияют следующие факторы:

  • Видимость элемента (display: none, visibility: hidden исключают элемент).
  • Наличие атрибута disabled.
  • Наличие отрицательного tabindex (элемент исключается из обычной последовательности табуляции, но может быть фокусирован программно).
  • Семантическая роль элемента (кнопки, ссылки, поля ввода, текстовые области и т.д.).

Невалидные контейнеры

Невалидные контейнеры — это элементы, которые сами могут содержать фокусируемые элементы, но не должны участвовать в процессе табуляции. Сюда относятся контейнеры, которые по дизайну не предназначены для прямого фокуса, либо элементы с нарушенной видимостью или интерактивностью.

Примеры и правила исключения

  1. Скрытые контейнеры Если контейнер или любой его предок имеет display: none или visibility: hidden, все его дочерние элементы автоматически считаются невидимыми для Tabbable.

    <div style="display: none;">
        <button>Кнопка</button>
    </div>

    В этом примере кнопка не попадет в массив tabbable элементов.

  2. Контейнеры с disabled Формы, fieldset и отдельные элементы с атрибутом disabled исключаются.

    <fieldset disabled>
        <input type="text" />
    </fieldset>

    Любые дочерние элементы внутри fieldset не будут фокусируемыми.

  3. Элементы с отрицательным tabindex tabindex="-1" исключает элемент из стандартного потока табуляции. Tabbable учитывает это при генерации последовательности.

  4. Элементы с CSS, блокирующим интерактивность Например, pointer-events: none или opacity: 0 не всегда исключает элемент, но в сочетании с visibility: hidden делает его недоступным для фокуса.

Обход невалидных контейнеров

Для проверки элементов, находящихся внутри потенциально невалидных контейнеров, Tabbable использует рекурсивный обход DOM. Алгоритм следующий:

  1. Для каждого дочернего элемента контейнера проверяется валидность (видимость, интерактивность).
  2. Если контейнер невидим, дочерние элементы пропускаются.
  3. Если контейнер валиден, проверяется каждый дочерний элемент на соответствие правилам фокусируемости.

Это обеспечивает корректную генерацию последовательности табуляции даже в сложных вложенных структурах.

Настройка фильтров и кастомизация

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

import { tabbable } from 'tabbable';

const elements = tabbable(document.body, {
    getShadowRoot: true,
    includeContainer: false,
    filter: (element) => {
        // Игнорировать элементы внутри контейнера с классом .ignore
        return !element.closest('.ignore');
    }
});

Параметр includeContainer управляет тем, будут ли считаться сами контейнеры фокусируемыми, если они соответствуют правилам. Параметр getShadowRoot позволяет искать tabbable элементы внутри Shadow DOM.

Взаимодействие с фреймами и Shadow DOM

Невалидные контейнеры могут находиться внутри iframe или Shadow DOM. Tabbable корректно работает с:

  • Shadow DOM — рекурсивно обходит вложенные деревья, соблюдая видимость и интерактивность.
  • iFrame — требует явного доступа к контенту фрейма; невидимые или отключенные контейнеры игнорируются.

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

  • Проверять все предки элемента на валидность, а не только сам элемент.
  • Использовать tabindex с осторожностью: отрицательные значения исключают элемент из естественной последовательности.
  • Для сложных UI компонентов, таких как модальные окна или всплывающие панели, использовать фильтры для исключения невидимых контейнеров.
  • Shadow DOM требует getShadowRoot: true для полноценной работы.

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