Отрицательные значения tabindex

В HTML элементам, способным принимать фокус, можно назначать атрибут tabindex. Этот атрибут определяет порядок перехода по элементам при навигации с клавиатуры (обычно с помощью клавиши Tab). Значения tabindex могут быть положительными, нулевыми и отрицательными. Особый интерес представляют отрицательные значения, в первую очередь tabindex="-1".

Ключевое свойство отрицательного tabindex: элемент не включается в последовательность табуляции, но остаётся доступным для фокусировки программно, через JavaScript или с помощью методов вроде .focus(). Это позволяет управлять навигацией, не нарушая естественного порядка элементов.

<button>Кнопка 1</button>
<button tabindex="-1">Кнопка 2</button>
<button>Кнопка 3</button>

В этом примере при навигации клавишей Tab фокус перейдёт с «Кнопка 1» на «Кнопка 3», пропуская вторую кнопку. Тем не менее, её можно программно сфокусировать:

document.querySelector('button[tabindex="-1"]').focus();

Использование в библиотеке Tabbable

Библиотека Tabbable предназначена для определения фокусируемых и табулируемых элементов на странице. Она учитывает атрибуты tabindex, CSS-свойства display и visibility, а также состояния элементов (disabled, hidden и др.).

Методы библиотеки

  1. tabbable(container) Возвращает массив элементов внутри container, которые могут быть доступны через Tab.

    • Элементы с tabindex="-1" не включаются в массив, так как они исключены из последовательности табуляции.
  2. focusable(container) Возвращает массив элементов, которые могут получить фокус любой доступной методикой, включая программную.

    • Элементы с tabindex="-1" включаются, поскольку они фокусируемы через .focus().
import tabbable from 'tabbable';

const allTabbable = tabbable(document.body); // Только элементы с положительным tabindex и tabindex=0
const allFocusable = tabbable.focusable(document.body); // Включает tabindex="-1"

Практическая логика

  • Элементы с tabindex="-1" применяются для временного отключения табуляции. Например, модальные окна часто содержат элементы с tabindex="-1", которые становятся доступными только после открытия окна.
  • Динамическое управление: библиотека позволяет проверять фокусируемые элементы в любой момент, что полезно для SPA, где DOM постоянно изменяется.

Особенности отрицательного tabindex

  1. Не ломает естественный поток Использование tabindex="-1" не меняет порядок фокусируемых элементов в DOM. Это важно для сохранения предсказуемости интерфейса.

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

  3. Совместимость с библиотекой Tabbable Tabbable учитывает отрицательные tabindex только при вычислении элементов через метод focusable, что обеспечивает корректную фильтрацию для управления клавиатурой.

  4. Влияние на доступность Элементы с tabindex="-1" исключаются из обычной навигации Tab, поэтому их использование должно быть оправдано: они не должны скрывать критически важные функции интерфейса.

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

Модальное окно:

<div class="modal" hidden>
  <button>Закрыть</button>
  <input type="text" tabindex="-1" value="Скрытый элемент">
</div>
import { tabbable } from 'tabbable';

const modal = document.querySelector('.modal');
modal.hidden = false;

const focusableElements = tabbable.focusable(modal); 
// ['button', 'input'] — input включен несмотря на tabindex="-1"

focusableElements[1].focus(); // Программно ставим фокус на input

Управление навигацией:

  • Переход Tab пропускает tabindex="-1".
  • Скрипты могут временно изменить tabindex на 0, чтобы элемент стал частью последовательности.
const el = document.querySelector('input');
el.setAttribute('tabindex', '0'); // Теперь включен в Tab
el.removeAttribute('tabindex');    // Возвращаем к default (focusable по умолчанию)

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

  • Использовать отрицательный tabindex для элементов, которые должны быть фокусируемыми только программно.
  • Не использовать tabindex="-1" для важных кнопок и ссылок, доступ к которым необходим клавиатурой.
  • Проверять актуальный список фокусируемых элементов через Tabbable при динамическом изменении DOM.
  • Сочетать с методами focusable() и tabbable() для точного контроля над пользовательской навигацией.

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