Разница между tabbable и focusable

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


Focusable

Focusable — это элемент, который может получать фокус, независимо от того, осуществляется ли навигация по клавише Tab. Ключевые аспекты:

  • Элемент считается focusable, если на него можно установить фокус программно с помощью element.focus().
  • Стандартные HTML-элементы, которые обычно focusable: <input>, <button>, <select>, <textarea>, <a> с атрибутом href.
  • Focusable элементы могут быть временно недоступны для клавиатуры, например, если установлено tabindex="-1", но всё ещё поддерживают программное получение фокуса.
  • Свойство disabled делает элемент недоступным для фокуса: элемент перестаёт быть focusable.

Примеры focusable элементов:

<button>Click me</button>
<input type="text">
<a href="#">Link</a>
<div tabindex="0">Focusable div</div>
<div tabindex="-1">Programmatically focusable</div>

В этом примере последний <div> нельзя достичь с помощью Tab, но можно вызвать document.querySelector('div').focus().


Tabbable

Tabbable — это подмножество focusable элементов, на которые можно попасть с помощью клавиши Tab. Отличительные особенности:

  • Tabbable элементы участвуют в естественном порядке табуляции документа.
  • Элементы с tabindex="-1" являются focusable, но не tabbable.
  • Элементы с tabindex="0" или положительным значением tabindex становятся tabbable и включаются в последовательность Tab.

Примеры tabbable элементов:

<button>Button</button>
<a href="#">Link</a>
<input type="text">
<div tabindex="0">Tabbable div</div>
<div tabindex="-1">Not tabbable</div>

Здесь первые четыре элемента будут доступны через Tab, последний <div> — нет, хотя на него можно установить фокус программно.


Практическое использование в библиотеке tabbable

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

import { tabbable } from 'tabbable';

const container = document.getElementById('modal');
const tabbableElements = tabbable(container);

console.log(tabbableElements); // массив элементов доступных через Tab

Ключевые моменты:

  • tabbable() возвращает только те элементы, которые участвуют в последовательности Tab, исключая скрытые или с tabindex="-1".
  • Focusable элементы, недоступные через Tab, не попадут в результат, что позволяет точно управлять циклом фокуса в UI-компонентах.
  • Это особенно важно для реализации trap focus в модальных окнах: цикл фокуса ограничивается только tabbable элементами внутри модалки.

Атрибут tabindex и влияние на tabbable и focusable

  • tabindex="0" — делает элемент tabbable, вставляя его в естественный порядок документа.
  • tabindex="-1" — делает элемент focusable, но не tabbable.
  • tabindex с положительным числом — задаёт пользовательский порядок табуляции, элемент становится tabbable с приоритетом перед элементами с tabindex="0".

Влияние CSS и состояния элемента

Некоторые стили и свойства могут сделать элемент невидимым или недоступным для фокуса:

  • display: none или visibility: hidden — элемент теряет статус focusable и tabbable.
  • disabled — элемент не может быть focusable, следовательно, и не tabbable.
  • Элементы с aria-hidden="true" также исключаются из tabbable списка для улучшения доступности.

Основные различия в таблице

Свойство Focusable Tabbable
Доступ через Tab Не обязательно Обязательно
Доступ программно Да Да
tabindex="-1" Да Нет
tabindex="0" Да Да
Участие в последовательности Tab Нет обязательно Да
Скрытые элементы Нет Нет

Итоговая логика при работе с tabbable

  1. Все tabbable элементы являются focusable, но не все focusable элементы являются tabbable.
  2. Использование библиотеки tabbable позволяет точно фильтровать элементы для Tab-навигации, избегая ошибок при реализации доступного UI.
  3. При управлении фокусом важно учитывать tabindex, disabled и CSS-состояние элементов, чтобы корректно различать focusable и tabbable.

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