Кросс-браузерное тестирование

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


Импорт и использование

Tabbable можно подключить через npm:

import { tabbable } from 'tabbable';

или через CommonJS:

const { tabbable } = require('tabbable');

После подключения функция tabbable(container) возвращает массив элементов внутри указанного контейнера, доступных для фокусировки. Если контейнер не указан, проверка выполняется по всему документу:

const focusableElements = tabbable(document.body);

Каждый элемент в массиве соответствует критериям, установленным библиотекой: элемент видим, не отключён, поддерживает фокусировку и соответствует стандартным правилам HTML.


Ключевые критерии фокусируемости

  1. Видимость элемента Tabbable игнорирует элементы с display: none, visibility: hidden, opacity: 0 или с нулевыми размерами (width: 0 и height: 0). Это обеспечивает корректное поведение при навигации по странице с динамически скрываемыми элементами.

  2. Атрибут tabindex

    • Значение tabindex="0" — элемент включается в естественный порядок табуляции.
    • Значение tabindex="-1" — элемент исключён из таб-циклов, но может быть фокусирован программно.
    • Положительные значения tabindex="1", tabindex="2" и т.д. задают приоритет в порядке перехода. Tabbable корректно учитывает этот порядок.
  3. Состояние disabled Элементы с disabled (например, <button disabled> или <input disabled>) исключаются из списка, так как они не должны получать фокус.

  4. Элементы контента Элементы вроде <a href="">, <button>, <input>, <textarea>, <select> и <iframe> считаются фокусируемыми по умолчанию, если они не отключены и видимы.


Особенности кросс-браузерной работы

Tabbable учитывает различия в реализации фокуса в браузерах:

  • Chrome, Firefox, Edge: поддерживают стандартный порядок табуляции, однако элементы с contenteditable требуют явного включения в tabindex.
  • Safari: некоторые элементы <fieldset> и <legend> ведут себя иначе при фокусировке; библиотека корректирует их поведение.
  • IE11/Legacy Edge: поддержка opacity: 0 и скрытых контейнеров реализована через специфические проверки offsetWidth и offsetHeight.

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


Функции и опции

Tabbable предоставляет несколько полезных инструментов для управления фокусом:

  1. tabbable(container, options)

    • container — родительский элемент, в котором выполняется поиск.

    • options — объект с дополнительными настройками, например:

      • includeContainer — включает сам контейнер в список, если он фокусируемый.
      • getShadowRoot — поддержка веб-компонентов и shadow DOM.
const options = { includeContainer: true };
const focusables = tabbable(document.querySelector('#modal'), options);
  1. Shadow DOM Tabbable может работать с элементами внутри shadow root, что критично для современных веб-компонентов. Функция getShadowRoot позволяет рекурсивно находить все фокусируемые элементы.

  2. Фильтрация и сортировка Результирующий массив можно фильтровать по классам, типам элементов или атрибутам. Tabbable уже сортирует элементы по порядку табуляции, включая положительные tabindex перед стандартными элементами.


Практические сценарии

  • Модальные окна Для реализации замыкания фокуса внутри модального окна можно получить массив всех tabbable-элементов внутри окна и перехватывать клавишу Tab:
const modal = document.getElementById('modal');
const focusables = tabbable(modal);

modal.addEventListener('keydown', (e) => {
  if (e.key === 'Tab') {
    const first = focusables[0];
    const last = focusables[focusables.length - 1];

    if (e.shiftKey && document.activeElement === first) {
      e.preventDefault();
      last.focus();
    } else if (!e.shiftKey && document.activeElement === last) {
      e.preventDefault();
      first.focus();
    }
  }
});
  • Доступность сложных форм Tabbable позволяет проверять порядок табуляции в многоуровневых формах с динамически добавляемыми элементами, обеспечивая корректное поведение даже при скрытии или блокировке полей.

  • Автоматизированное тестирование В интеграции с Cypress, Playwright или Selenium можно использовать Tabbable для проверки доступности элементов и их последовательности табуляции во всех поддерживаемых браузерах.


Рекомендации по использованию

  • Всегда перед манипуляциями с фокусом использовать актуальный список от Tabbable, так как DOM может меняться динамически.
  • Для компонентов с динамическими списками (tabs, accordions) использовать Tabbable при каждом рендере, чтобы корректно обновлять порядок фокуса.
  • При работе с shadow DOM обязательно включать опцию getShadowRoot, иначе элементы внутри компонентов не будут учитываться.
  • Проверять комбинации tabindex и disabled для элементов, созданных программно, чтобы избежать попадания невидимых элементов в список.

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