Эксперт по доступности
Проверка и исправление доступности
---
name: accessibility-expert
description: Проверяет и устраняет проблемы доступности для соответствия WCAG и совместимости со вспомогательными технологиями. Используй при (1) аудите интерфейса на нарушения доступности, (2) реализации клавиатурной навигации или поддержки экранных дикторов, (3) исправлении контраста цветов или индикаторов фокуса, (4) обеспечении доступности форм и обработки ошибок, (5) создании реализаций ARIA.
---
# Проверка и исправление доступности
## Конфигурация
- **Уровень WCAG**: ${wcag_level:AA}
- **Целевой компонент**: ${component_name:Application}
- **Стандарт соответствия**: ${compliance_standard:WCAG 2.1}
- **Объём проверки**: ${testing_scope:full-audit}
- **Экранный диктор**: ${screen_reader:NVDA}
## Краткий справочник WCAG 2.1
### Уровни соответствия
| Уровень | Требование | Частые проблемы |
|-------|-------------|---------------|
| A | Минимальная основа | Нет альтернативного текста, клавиатурного доступа, подписей полей формы |
| ${wcag_level:AA} | Стандартная цель | Контраст < 4.5:1, нет индикаторов фокуса, плохая структура заголовков |
| AAA | Повышенный уровень | Контраст < 7:1, жестовый язык, расширенное аудиоописание |
### Четыре принципа (POUR)
1. **Воспринимаемость**: содержимое доступно органам чувств — альтернативный текст, субтитры, контраст.
2. **Управляемость**: навигация по интерфейсу возможна всеми способами ввода — клавиатурой, касанием, голосом.
3. **Понятность**: содержимое и интерфейс предсказуемы и читаемы.
4. **Надёжность**: работа с текущими и будущими вспомогательными технологиями.
## Матрица серьёзности нарушений
```
КРИТИЧЕСКИЕ (исправить немедленно):
- Нет доступа с клавиатуры к интерактивным элементам.
- Отсутствуют подписи полей формы.
- Изображения без альтернативного текста.
- Автоматическое воспроизведение аудио без управления.
- Клавиатурные ловушки.
ВЫСОКИЕ (исправить до выпуска):
- Контраст ниже ${min_contrast_ratio:4.5}:1 для текста или 3:1 для крупного текста.
- Отсутствуют ссылки пропуска блоков.
- Неправильная иерархия заголовков.
- Фокус не виден.
- Ошибки не обозначены.
СРЕДНИЕ (исправить в следующем спринте):
- Непоследовательная навигация.
- Отсутствуют ориентиры страницы.
- Плохой текст ссылок: «нажмите здесь».
- Отсутствует языковой атрибут.
- Сложные таблицы без заголовков.
НИЗКИЕ (бэклог):
- Регулирование временных ограничений.
- Несколько способов найти содержимое.
- Контекстная помощь.
```
## Дерево решений для тестирования
```
Начало: что ты проверяешь?
|
+-- Новый компонент
| +-- Есть интерактивные элементы? --> Список проверки клавиатурной навигации
| +-- Есть текст? --> Проверка контраста и структуры заголовков
| +-- Есть изображения? --> Проверка уместности альтернативного текста
| +-- Есть формы? --> Список проверки доступности форм
|
+-- Существующая страница / функция
| +-- Сначала автоматическое сканирование: axe-core, Lighthouse
| +-- Ручной проход с клавиатурой
| +-- Проверка экранным диктором
| +-- Выборочная проверка контраста цветов
|
+-- Сторонний виджет
+-- Проверить реализацию ARIA
+-- Проверить поддержку клавиатуры
+-- Протестировать экранным диктором
+-- Задокументировать ограничения
```
## Список проверки клавиатурной навигации
```markdown
[ ] Все интерактивные элементы доступны через Tab.
[ ] Порядок Tab соответствует визуальной / логической последовательности.
[ ] Индикатор фокуса виден: контур ${focus_indicator_width:2}px+, контраст 3:1.
[ ] Нет клавиатурных ловушек: из всех элементов можно выйти через Tab.
[ ] Ссылка пропуска блоков — первый элемент, доступный для фокусировки.
[ ] Enter активирует кнопки и ссылки.
[ ] Пробел активирует флажки и кнопки.
[ ] Стрелки обеспечивают навигацию внутри компонентов: вкладок, меню, групп переключателей.
[ ] Escape закрывает модальные окна и раскрывающиеся списки.
[ ] Модальные окна удерживают фокус до закрытия.
```
## Шаблоны тестирования экранным диктором
### Основные объявления, которые нужно проверить
```
Интерактивные элементы:
Кнопка: "[label], кнопка"
Ссылка: "[text], ссылка"
Флажок: "[label], флажок, [checked/unchecked]"
Переключатель: "[label], переключатель, [selected], [position] из [total]"
Комбинированный список: "[label], комбинированный список, [collapsed/expanded]"
Динамическое содержимое:
Загрузка: используй aria-busy="true" у контейнера.
Статус: используй role="status" для некритичных обновлений.
Оповещение: используй role="alert" для критических сообщений.
Живые области: aria-live="${aria_live_politeness:polite}"
Формы:
Обязательность: вместе с подписью произносится «обязательное».
Некорректность: «некорректный ввод» вместе с сообщением об ошибке.
Инструкции: произносятся вместе с подписью через aria-describedby.
```
### Последовательность тестирования
1. Пройди всю страницу клавишей Tab, слушая объявления.
2. Проверь навигацию по заголовкам: клавиша H в экранном дикторе.
3. Проверь навигацию по ориентирам: клавиша D / ротор.
4. Проверь таблицы: клавиша T, стрелки внутри таблицы.
5. Проверь формы: клавиша F, полная отправка формы.
6. Проверь обновления динамического содержимого: проверка живых областей.
## Требования к цветовому контрасту
| Тип текста | Минимальное соотношение | Повышенный уровень (AAA) |
|-----------|---------------|----------------|
| Обычный текст (<${large_text_threshold:18}pt) | ${min_contrast_ratio:4.5}:1 | 7:1 |
| Крупный текст (>=${large_text_threshold:18}pt или 14pt полужирный) | 3:1 | 4.5:1 |
| Компоненты интерфейса и графика | 3:1 | Неприменимо |
| Индикаторы фокуса | 3:1 | Неприменимо |
### Порядок проверки контраста
```
1. Определи все пары цветов переднего плана и фона.
2. Рассчитай соотношение контраста: (L1 + 0.05) / (L2 + 0.05)
где L1 — более высокая яркость, L2 — более низкая яркость.
3. Частые нарушения для проверки:
- Текст-заполнитель: часто слишком светлый.
- Неактивное состояние: исключено из требований, но учитывай удобство.
- Ссылки внутри текста: должны отличаться от текста.
- Состояния ошибки / успеха на цветном фоне.
- Текст поверх изображений: используй наложение или тень текста.
```
## Руководство по реализации ARIA
### Первое правило ARIA
По возможности используй нативные элементы HTML. ARIA предназначена только для пользовательских виджетов.
```html
<!-- WRONG: ARIA on native element -->
<div role="button" tabindex="0">Submit</div>
<!-- RIGHT: Native button -->
<button type="submit">Submit</button>
```
### Когда нужна ARIA
```html
<!-- Custom tabs -->
<div role="tablist">
<button role="tab" aria-selected="true" aria-controls="panel1">Tab 1</button>
<button role="tab" aria-selected="false" aria-controls="panel2">Tab 2</button>
</div>
<div role="tabpanel" id="panel1">Content 1</div>
<div role="tabpanel" id="panel2" hidden>Content 2</div>
<!-- Expandable section -->
<button aria-expanded="false" aria-controls="content">Show details</button>
<div id="content" hidden>Expandable content</div>
<!-- Modal dialog -->
<div role="dialog" aria-modal="true" aria-labelledby="title">
<h2 id="title">Dialog Title</h2>
<!-- content -->
</div>
<!-- Live region for dynamic updates -->
<div aria-live="${aria_live_politeness:polite}" aria-atomic="true">
<!-- Status messages injected here -->
</div>
```
### Частые ошибки ARIA
```
- role="button" без поддержки клавиатуры: Enter / пробел.
- aria-label дублирует видимый текст.
- aria-hidden="true" на элементах, доступных для фокусировки.
- Нет aria-expanded у кнопок раскрытия.
- Некорректная ссылка aria-controls.
- Использование aria-describedby для существенной информации.
```
## Шаблоны доступности форм
### Необходимая структура формы
```html
<form>
<!-- Explicit label association -->
<label for="email">Email address</label>
<input type="email" id="email" name="email"
aria-required="true"
aria-describedby="email-hint email-error">
<span id="email-hint">We'll never share your email</span>
<span id="email-error" role="alert"></span>
<!-- Group related fields -->
<fieldset>
<legend>Shipping address</legend>
<!-- address fields -->
</fieldset>
<!-- Clear submit button -->
<button type="submit">Complete order</button>
</form>
```
### Требования к обработке ошибок
```
1. Обозначь поле с ошибкой: выделение и значок.
2. Опиши ошибку текстом, а не только цветом.
3. Свяжи ошибку с полем через aria-describedby.
4. Сообщи об ошибке экранным дикторам через role="alert".
5. При неудачной отправке переведи фокус на первую ошибку.
6. По возможности предложи способы исправления.
```
## Список проверки мобильной доступности
```markdown
Области касания:
[ ] Минимум ${touch_target_size:44}x${touch_target_size:44} CSS-пикселей.
[ ] Достаточное расстояние между областями: ${touch_target_spacing:8}px+.
[ ] Действие касания не зависит от траектории жеста.
Жесты:
[ ] Есть альтернатива жестам несколькими пальцами.
[ ] Есть альтернатива жестам с траекторией: свайпам.
[ ] Действия, основанные на движении, имеют альтернативы.
Экранный диктор (iOS/Android):
[ ] Для изображений и значков задан accessibilityLabel.
[ ] Для сложных взаимодействий задан accessibilityHint.
[ ] accessibilityRole соответствует поведению элемента.
[ ] Порядок фокуса соответствует визуальной компоновке.
```
## Интеграция автоматического тестирования
### Хук перед коммитом
```bash
#!/bin/bash
# Run axe-core on changed files
npx axe-core-cli --exit src/**/*.html
# Check for common issues
grep -r "onClick.*div\|onClick.*span" src/ && \
echo "Warning: Click handler on non-interactive element" && exit 1
```
### Проверки в CI
```yaml
accessibility-audit:
script:
- npx pa11y-ci --config .pa11yci.json
- npx lighthouse --accessibility --output=json
artifacts:
paths:
- accessibility-report.json
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
```
### Минимальные пороги CI
```
axe-core: 0 критических нарушений, 0 серьёзных нарушений
Доступность Lighthouse: >= ${lighthouse_a11y_threshold:90}
pa11y: 0 ошибок, предупреждения допустимы
```
## Система приоритетов исправления
```
Приоритет 1 (этот спринт):
- Блокирует выполнение задачи пользователем.
- Риск несоблюдения закона.
- Затрагивает многих пользователей.
Приоритет 2 (следующий спринт):
- Существенно ухудшает взаимодействие.
- Автоматические инструменты отмечают как ошибку.
- Нарушает требование ${wcag_level:AA}.
Приоритет 3 (бэклог):
- Незначительное неудобство.
- Нарушает только AAA.
- Затрагивает пограничные случаи.
Приоритет 4 (улучшение):
- Повышает удобство для всех.
- Лучшая практика, а не требование.
- Подготовка к будущим изменениям.
```
## Проверочный список верификации
Прежде чем отметить работу над доступностью как завершённую:
```markdown
Автоматические проверки:
[ ] axe-core: 0 нарушений.
[ ] Доступность Lighthouse: ${lighthouse_a11y_threshold:90}+.
[ ] Валидация HTML проходит.
[ ] В консоли нет предупреждений о доступности.
Клавиатура:
[ ] Все задачи выполняются только клавиатурой.
[ ] Фокус виден постоянно.
[ ] Порядок Tab логичен.
[ ] Нет клавиатурных ловушек.
Экранный диктор: протестировать хотя бы с одним:
[ ] Всё содержимое произносится.
[ ] Интерактивные элементы подписаны.
[ ] Ошибки и обновления объявляются.
[ ] Навигация эффективна.
Визуальные проверки:
[ ] Весь текст проходит проверку контраста.
[ ] Компоненты интерфейса проходят проверку контраста.
[ ] Работа при масштабе ${zoom_level:200}%.
[ ] Работа в режиме высокого контраста.
[ ] Нет мигания, способного вызвать приступ.
Формы:
[ ] Все поля подписаны.
[ ] Ошибки можно определить.
[ ] Обязательные поля обозначены.
[ ] Инструкции доступны.
```
## Шаблон документации
```markdown
# Заявление о доступности
## Статус соответствия
Этот [website/application] [fully/partially] соответствует ${compliance_standard:WCAG 2.1} уровня ${wcag_level:AA}.
## Известные ограничения
| Функция | Проблема | Обходной способ | Срок |
|---------|-------|------------|----------|
| [Feature] | [Description] | [Alternative] | [Fix date] |
## Проверенные вспомогательные технологии
- ${screen_reader:NVDA} [version] с Firefox [version]
- VoiceOver с Safari [version]
- JAWS [version] с Chrome [version]
## Обратная связь
По вопросам доступности обращайтесь на [email].
Последнее обновление: [date]
```Текст доступен бесплатно по CC0 1.0. Источники и лицензии.
Как использовать навык
Прочитайте инструкцию и проверьте, какие файлы, инструменты и подключения ей нужны. Перенесите навык в совместимое приложение для AI-агентов или используйте подходящие шаги в чате. Если навык состоит из нескольких файлов, сохраните их структуру.