Чтобы совместить HTML5 семантику и доступность сайта a11y, размечайте страницу смысловыми блоками (header/nav/main/section/article/footer), держите последовательную иерархию заголовков, подписывайте поля форм через label, давайте текстовые альтернативы медиа и применяйте ARIA только там, где нативной семантики недостаточно. Ниже - чек-лист и безопасные шаги для правок.
Короткий чек-лист для быстрой проверки семантики и a11y
- Есть один
<main>на страницу; навигация в<nav>, шапка/подвал - в<header>/<footer>. - Заголовки идут без пропусков уровней; структура читается скринридером и по оглавлению/outline.
- У всех полей форм есть
и понятные сообщения об ошибках; обязательность и формат ввода обозначены. - У изображений есть корректный
alt; у видео - субтитры/транскрипт по необходимости; фокус клавиатуры всегда виден. - ARIA не дублирует нативные роли; нет
roleна интерактивных элементах без причины. - Быстрый прогон: клавиатура (Tab/Shift+Tab/Enter/Escape) + авто-проверка (Lighthouse/axe) + ручная проверка заголовков и форм.
Структурные элементы: когда и как применять section, article, nav, header, footer
Семантическая верстка HTML5 нужна, когда вы хотите, чтобы документ был понятен не только визуально, но и по структуре: для скринридеров, поисковых роботов, автоматических тестов и поддержки. Используйте HTML5 семантические теги, если блок имеет роль в документе, а не просто нужен для сетки.
- Когда подходит: страницы с повторяющимися зонами (шапка, меню, контент, сайдбар, подвал), статьи/карточки, списки публикаций, многоуровневая навигация.
- Как применять:
<header>- вводная часть страницы/раздела (может встречаться внутри<article>).<nav>- блок ссылок для навигации (главное меню, хлебные крошки, пагинация).<main>- уникальный основной контент, один раз на страницу.<section>- смысловой раздел с заголовком (обычно нужен<h2>...</h2>или ниже).<article>- самодостаточная единица (пост, карточка новости, комментарий), которую можно вынести/процитировать.<footer>- завершающая часть страницы/раздела (контакты, ссылки, юридическая информация).
- Когда не стоит: не используйте
<section>как замену<div>ради стилей; не делайте<nav>вокруг одиночной ссылки; не создавайте несколько<main>.
Текстовая семантика: заголовки, абзацы, списки и их роль в навигации
Для уверенной проверки структуры вам понадобятся: DevTools (Accessibility tree), автоматический анализатор (например, axe DevTools или Lighthouse) и базовое умение прогонять страницу только клавиатурой. Для ручной проверки полезны: просмотр Outline/структуры заголовков (расширение/инструмент) и любой скринридер (NVDA/VoiceOver) хотя бы на базовом уровне.
- Заголовки: один логический
<h1>(на странице он может быть визуально скрыт), дальше - последовательные уровни без "скачков" ради размера. - Абзацы: текстовые блоки - в
<p>; не используйте<br>как разметку структуры. - Списки: группы однотипных элементов - в
<ul>/<ol>; пункты меню/фич/шагов - только<li>. - Навигация по странице: при корректной семантике пользователь скринридера может прыгать по заголовкам и спискам, поэтому не "ломайте" структуру ради CSS.
Формы и управляющие элементы: метки, группы, валидация и aria-атрибуты

-
Свяжите поля с метками. Для каждого элемента ввода используйте
+idили оборачивайте элемент управления в....- Fast-track: добавьте видимую подпись (например,
Email) иid="email"прямо сейчас. - Deep-audit: проверьте, что "визуальная подпись" совпадает с доступным именем (Accessible Name) и нет дублирования через
aria-label.
- Fast-track: добавьте видимую подпись (например,
-
Группируйте связанные поля. Используйте
<fieldset>и<legend>для групп (например, способ доставки, диапазоны, набор чекбоксов).- Fast-track: оберните группу чекбоксов в
<fieldset>и добавьте короткий<legend>. - Deep-audit: проверьте, что порядок Tab соответствует визуальному, а легенда не скрыта так, что становится недоступной скринридеру.
- Fast-track: оберните группу чекбоксов в
-
Делайте ошибки понятными и связанными. Сообщение об ошибке должно быть текстом рядом с полем и программно связано через
aria-describedby; статус обязательности передавайте нативно (required) и/или текстом.- Fast-track: добавьте блок
<span id="email-error">Введите корректный email</span>и у поляaria-describedby="email-error". - Deep-audit: при отправке фокус переводите на первый ошибочный элемент и объявляйте общий статус (например, через
role="alert"для сводки ошибок, если она есть).
- Fast-track: добавьте блок
-
Используйте правильные типы и атрибуты.
type="email",autocomplete,inputmode,min/maxиpatternулучшают ввод и уменьшают ошибки.- Fast-track: проставьте
autocompleteи корректныеtypeдля основных полей. - Deep-audit: проверьте, что валидация не завязана только на цвет и что подсказка формата есть до ошибки.
- Fast-track: проставьте
-
Не подменяйте нативные элементы кастомом без нужды. Если делаете кастомные селекты/переключатели, обеспечьте полное управление с клавиатуры и корректные роли/состояния.
- Fast-track: по возможности вернитесь к нативному
<select>/. - Deep-audit: для кастома реализуйте управление стрелками, Escape, Enter, озвучивание состояния и корректный фокус-менеджмент.
- Fast-track: по возможности вернитесь к нативному
Быстрый режим
- Проверьте: у каждого поля есть
и уникальныйid. - Добавьте
requiredи текстовую подсказку формата (не только цвет/иконку). - Свяжите ошибки через
aria-describedbyи показывайте их рядом с полем. - Проставьте
autocompleteдля типовых данных и корректныеtype.
Мультимедиа и интерактивные компоненты: доступные img, video, canvas и tabindex
- У
<img>есть уместныйalt: описание смысла, а не внешнего вида; у декоративных - пустойalt="". - У кликабельных изображений понятное доступное имя (обычно через текст рядом или
aria-labelна ссылке/кнопке, если текста нет). - Видео/аудио: есть контролы, а при необходимости - субтитры/транскрипт (зависит от контента и аудитории).
<canvas>: есть альтернативный текст внутри тега или отдельное доступное представление результата (таблица/текст), если canvas несет информацию.- Фокус клавиатуры виден всегда; не убирайте
outlineбез замены на заметный стиль. - Не используйте положительный
tabindex(> 0); для редких случаев используйтеtabindex="0"(включить в порядок) или-1(программный фокус). - Кастомные интерактивы реагируют на Enter/Space и имеют корректную роль (лучше - нативная кнопка/ссылка).
Практическое ARIA: корректное использование ролей и распространённые анти-паттерны

- Дублирование семантики: не ставьте
role="button"на<button>иrole="link"на<a>- это мешает, а не помогает. - ARIA вместо HTML: не пытайтесь "починить" отсутствие
однимaria-label, если видимый текст уже есть - лучше связать корректно. - Неполные состояния: если используете
aria-expanded, обновляйте его при каждом раскрытии/схлопывании, иначе скринридер будет сообщать неверное состояние. - Лишние landmark-роли: не размечайте всё как
role="region"; регионы должны быть редкими и именованными (aria-label/aria-labelledby). - Скрытие контента: не скрывайте фокусируемые элементы через CSS так, что они остаются в таб-цепочке; при скрытии убирайте доступность корректно.
role="presentation"/role="none"без понимания: можно сломать списки/таблицы и чтение; применяйте только к строго декоративным оберткам.- Живые регионы где попало:
aria-liveиспользуйте дозировано, иначе получатся "болтливые" интерфейсы и шум.
Быстрое тестирование и приоритеты правок: инструменты, чек-лист и сценарии
Если вы делаете чек лист доступности сайта для рабочей команды, разбивайте правки по приоритету: блокирующие (невозможно пользоваться), значимые (сильно мешает), косметические (улучшение). Для аудита доступности сайта сочетайте авто-проверку и ручные сценарии: автоинструменты находят типовые ошибки, а ручной проход выявляет проблемы фокуса, смысла и текстов.
Компактная таблица: что проверить в первую очередь
| Элемент | Проверка | Приоритет | Заметки (fast-track / deep-audit) |
|---|---|---|---|
| Landmarks | Есть main, навигация в nav, уникальные области |
Высокий | Fast: расставить семантические контейнеры. Deep: именовать регионы, убрать лишние. |
| Заголовки | Иерархия без пропусков, смысловые названия | Высокий | Fast: исправить уровни. Deep: проверить логическую структуру разделов/section. |
| Формы | label, fieldset/legend, ошибки связаны |
Критичный | Fast: label + required + aria-describedby. Deep: фокус на ошибке, сводка ошибок. |
| Клавиатура | Всё доступно Tab/Enter/Space, фокус виден | Критичный | Fast: вернуть outline/стили фокуса. Deep: фокус-менеджмент модалок/меню. |
| Изображения | Корректный alt (смысл/декор) |
Средний | Fast: заполнить alt у ключевых. Deep: проверить ссылки/кнопки-иконки на доступное имя. |
| ARIA | Нет анти-паттернов, состояния обновляются | Средний | Fast: убрать лишние role. Deep: валидировать состояния (expanded, selected, live). |
Сценарии проверки (2-4 подхода)
- Fast-track: 15-30 минут перед релизом. Пройдите страницу только клавиатурой, проверьте видимость фокуса, заголовки и формы; затем прогоните Lighthouse/axe и исправьте критичные ошибки.
- Deep-audit: перед редизайном/большим рефакторингом. Проверьте дерево доступности (Accessibility Tree), роли/имена/состояния, сценарии модальных окон и динамики; дополните ручной проверкой скринридером.
- Регрессия в CI. Подключите автоматические проверки (axe-core в e2e/юнит-тестах) и минимальные ручные сценарии на компоненты с кастомным взаимодействием.
- Компонентный подход для дизайн-системы. Фиксируйте требования a11y на уровне компонентов (кнопки, поля, модалки) и реиспользуйте их - так семантическая верстка HTML5 будет стабильнее между страницами.
Практические ответы на частые сложности верстки для a11y
Можно ли делать всё на div и "починить" ARIA-атрибутами?
Технически можно, но это почти всегда дороже и ломается чаще. Нативные HTML5 семантические теги и элементы управления дают правильные роли, имена и клавиатурное поведение без ручной поддержки.
Сколько section допустимо на странице и нужен ли заголовок внутри?
Сколько нужно по смыслу, но каждый <section> должен представлять отдельный раздел и обычно иметь заголовок. Если заголовка нет и раздел не смысловой - используйте <div>.
Что важнее для доступность сайта a11y: alt у картинок или правильные заголовки?
Оба пункта важны, но заголовки и структура чаще влияют на навигацию по странице целиком. Alt критичен там, где изображение передает смысл или является единственным текстом кнопки/ссылки.
Когда использовать aria-label, а когда aria-labelledby?
aria-labelledby предпочтительнее, когда на странице уже есть видимый текст, который должен стать именем элемента. aria-label используйте, если видимого текста нет и его нельзя добавить.
Почему не стоит ставить tabindex="1"..."9" для "красивого" порядка?

Положительный tabindex создает отдельный, хрупкий порядок фокуса и часто ломается при новых элементах. Держите порядок фокуса естественным через DOM и используйте tabindex="0"/-1 точечно.
Как быстро понять, что чек лист доступности сайта закрыт на минимальном уровне?
Страница полностью проходится клавиатурой, фокус не теряется, формы подписаны и дают понятные ошибки, а авто-проверка не показывает критичных нарушений. Если есть кастомные компоненты - обязателен ручной сценарий на них.
Что включать в аудит доступности сайта, кроме автоматических отчетов?
Ручные сценарии: клавиатура, проверка заголовков, проверка доступных имен/состояний, модальные окна и динамические уведомления. Автоотчеты находят не всё, поэтому используйте их как фильтр, а не как финальный вердикт.


