← Назад к вопросам

Как реализовать доступность с клавиатуры?

2.0 Middle🔥 111 комментариев
#HTML и CSS

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Клавиатурная доступность (Keyboard Accessibility)

Что такое клавиатурная доступность

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

1. Фокусируемые элементы

Только определённые элементы могут получать фокус:

  • <button>, <a>, <input>, <select>, <textarea>
  • Пользовательские компоненты с tabindex="0"
// Хорошо: кнопка по умолчанию фокусируемая
<button onClick={handleClick}>Нажми</button>

// Плохо: div не может получить фокус
<div onClick={handleClick}>Нажми</div>

// Хорошо: добавляем фокусируемость custom компоненту
<div tabIndex={0} role="button" onClick={handleClick}>
  Кастомная кнопка
</div>

2. Порядок табуляции (Tab Order)

Tab order — это последовательность, в которой элементы получают фокус при нажатии Tab:

// Правильный порядок (слева направо, сверху вниз)
<form>
  <input placeholder="Имя" />        {/* tabindex: 1 */}
  <input placeholder="Email" />      {/* tabindex: 2 */}
  <button type="submit">Отправить</button> {/* tabindex: 3 */}
</form>

// Избегаем явного tabindex (кроме 0 или -1)
// ❌ Не делай так:
<button tabIndex={5}>Кнопка</button>

3. Видимый фокус

Всегда должно быть видно, какой элемент имеет фокус:

/* CSS для видимого фокуса */
button:focus {
  outline: 2px solid #0066cc;
  outline-offset: 2px;
}

/* Удалять outline НЕ СЛЕДУЕТ без замены */
/* ❌ Не делай так: */
button:focus {
  outline: none; /* потеря доступности */
}

/* ✅ Правильно: */
button:focus {
  outline: 2px solid transparent;
  outline-offset: 2px;
  box-shadow: 0 0 0 2px white, 0 0 0 4px #0066cc;
}

4. Обработка клавиатурных событий

function CustomButton({ onClick, onKeyDown }) {
  const handleKeyDown = (e) => {
    // Enter или Space активирует кнопку
    if (e.key === "Enter" || e.key === " ") {
      e.preventDefault();
      onClick?.();
    }
  };

  return (
    <div
      role="button"
      tabIndex={0}
      onClick={onClick}
      onKeyDown={handleKeyDown}
      aria-pressed="false"
    >
      Кастомная кнопка
    </div>
  );
}

5. ARIA атрибуты для управления

// Обозначь тип элемента
<div role="button">Клик</div>

// Состояние элемента
<button aria-pressed={isActive}>Toggle</button>

// Расширяемые элементы
<button aria-expanded={isOpen}>Меню</button>

// Скрытые элементы
<div aria-hidden="true">Декоративный элемент</div>

// Описание
<input aria-label="Поиск по сайту" />

6. Модальные диалоги

Элементы вне модали должны быть неактивны:

function Modal({ isOpen, children }) {
  return (
    <div role="dialog" aria-modal="true">
      {children}
    </div>
  );
}

7. Пропуск навигации (Skip Links)

function SkipLink() {
  return (
    <a href="#main-content" className="sr-only">
      Перейти к основному контенту
    </a>
  );
}

/* CSS для скрытия визуально, но видимо для экранных читателей */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

8. Тестирование

// Тест доступности с клавиатуры
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";

test("кнопка активируется при нажатии Enter", async () => {
  const user = userEvent.setup();
  const handleClick = vi.fn();
  
  render(<button onClick={handleClick}>Клик</button>);
  
  const button = screen.getByRole("button");
  button.focus();
  await user.keyboard("{Enter}");
  
  expect(handleClick).toHaveBeenCalled();
});

Итоги

Для полной клавиатурной доступности:

  • Используй семантичные HTML элементы
  • Обеспечь видимый фокус
  • Правильно обрабатывай клавиатурные события (Enter, Space)
  • Добавляй ARIA для пользовательских компонентов
  • Тестируй только с клавиатурой
Как реализовать доступность с клавиатуры? | PrepBro