
Этот вопрос преследует меня всю мою карьеру, начиная с 2013 года. Одни разработчики отвечают, потому что так правильно. Другие говорят про SEO. Третьи — ничего не говорят. А я считаю, что атрибут role
является отличным ответом на этот вопрос!
Я проведу исследование, которое покажет, как HTML влияет на конечный результат работы скринридеров. Оно будет состоять из двух этапов тестирования. В первом мы посмотрим, что происходит при использовании элементов <header>
, <nav>
, <main>
, <section>
и <footer>
. На втором этапе мы изучим, как скринридеры работают с заголовками.
Перед началом я дам несколько вводных. В исследовании я буду использовать скринридер JAWS. Опыт работы с ним не требуется. Каждый шаг подробно опишу. Для тех, кто хочет повторить за мной каждый тест, скачать его можно на официальном сайте. Ещё надо определиться с браузером, потому что скринридеры могут работать по-разному в различных браузерах. Я предлагаю остановить выбор на Chrome, чтобы у нас точно был одинаковый результат.
На этом с введением всё. Поехали!
Тест №1. Режим отображения основных областей страницы в JAWS
▍ Подготовка к тестированию
После установки запускаем JAWS. Откроется следующее окно:

В первом тесте нам понадобится режим отображения основных областей страницы, размеченных с помощью таких элементов, как: <header>
, <nav>
, <main>
, <aside>
, <section>
, <footer>
и <form>
.
Для демонстрации откроем страницу для скачивания JAWS. а затем нажмём сочетание клавиш insert + F3
. В ответ JAWS должен отобразить окно "Виртуальные характеристики HTML":


Нажимаем клавишу со стрелкой вниз (↓
). Останавливаемся на пункте "Список областей".

Выбираем его с помощью клавиши Enter
. В ответ появится окно "Области документа".

Сейчас я не буду объяснять, почему такие области отобразились. Ниже мы вернёмся к этой странице. А теперь мы готовы к тестированию. Начнём.
▍ Тестирование
Я буду использовать несколько версий разметки блока навигации. Отличаться они будут тем, что для разметки всей области будет использоваться элемент <div>
без и с role="navigation"
, а также элемент <nav>
. Мой выбор основан на том, что браузеры обработают и отобразят разметку одинаково, следовательно, многие разработчики подумают, что разницы между ними нет. Как раз проверим, так ли это в случае скринридеров.
Начнём с теста, где используется элемент div
без атрибута role
.
<body>
<div class="main-navigation">
<ul class="main-navigation__list">
<li class="main-navigation__group">
<a href="#home" class="main-navigation__point">Главная</a>
</li>
<li class="main-navigation__group">
<a href="#about-me" class="main-navigation__point">Обо мне</a>
</li>
<li class="main-navigation__group">
<a href="#my-projects" class="main-navigation__point">Мои проекты</a>
</li>
<li class="main-navigation__group">
<a href="#contacts" class="main-navigation__point">Контакты</a>
</li>
</ul>
</div>
</body>
Откроем страницу с разметкой, а потом нажмём insert + F3
и выберем режим "Список областей", как я показывал выше. В ответ JAWS скажет: "Области на странице не найдены". Пусто! JAWS не нашёл нашу навигацию.
Во втором тесте буду использовать более "правильный" элемент <nav>
.
<body>
<nav class="main-navigation">
<ul class="main-navigation__list">
<li class="main-navigation__group">
<a href="#home" class="main-navigation__point">Главная</a>
</li>
<li class="main-navigation__group">
<a href="#about-me" class="main-navigation__point">Обо мне</a>
</li>
<li class="main-navigation__group">
<a href="#my-projects" class="main-navigation__point">Мои проекты</a>
</li>
<li class="main-navigation__group">
<a href="#contacts" class="main-navigation__point">Контакты</a>
</li>
</ul>
</nav>
</body>
Мы видим, что JAWS нашёл нашу навигацию:

В третьем тесте заменю элемент <nav>
на элемент <div>
с атрибутом role
и значением navigation
.
<body>
<div role="navigation" class="main-navigation">
<ul class="main-navigation__list">
<li class="main-navigation__group">
<a href="#home" class="main-navigation__point">Главная</a>
</li>
<li class="main-navigation__group">
<a href="#about-me" class="main-navigation__point">Обо мне</a>
</li>
<li class="main-navigation__group">
<a href="#my-projects" class="main-navigation__point">Мои проекты</a>
</li>
<li class="main-navigation__group">
<a href="#contacts" class="main-navigation__point">Контакты</a>
</li>
</ul>
</div>
</body>
Для JAWS ничего не изменилось:

И это неспроста. Существует специальный стандарт ARIA in HTML, показывающий, как HTML влияет на работу скринридеров. Именно в нём для тестирования я нашёл, что роль navigation
используется для элемента <nav>
.
Мне кажется, что одной роли мало. Я хочу показать ещё несколько. Так, что протестирую скринридером ещё несколько страниц. Для начала мы вернёмся к странице для скачивания JAWS. После использования "Список областей" скринридер отображает следующее окно:

На этой странице есть три области. Область "Навигация" создана элементом <nav>
(ролью navigation
), "Основная область" — элементом <main>
(ролью main
), "Информация о содержимом" — элементом <footer>
(ролью contentinfo
).
Для второго примера я буду использовать главную страницу Smashing Magazine. На ней скринридер отобразит следующее окно:


К уже известным для нас областям он нашёл две области "Баннер", созданных элементом <header>
(ролью banner
).
Также надо отметить, что если проинспектировать код, то можно увидеть элементы <section>
на странице. Как я сказал выше, в режиме "Список областей" они отображаются, но на этой странице скринридер этого не сделал. Я не буду сейчас останавливаться подробно на причинах. Я напишу отдельную статью с пояснениями. Сейчас же важно сказать, что есть требования по использованию элементов <section>
и <form>
, из-за которых скринридер может не отобразить их.
▍ Вывод
Время для промежуточного вывода. Звучит он так: "Если мы используем элементы <header>
, <nav>
, <main>
, <aside>
, <section>
, <footer>
и <form>
, то пользователи получат быстрый доступ к областям, которые были размечены ими".
Тест №2. Режимы работы с заголовками страницы в JAWS
▍ Подготовка к тестированию
Для работы с заголовками JAWS предоставляет два режима. Первый, это список всех заголовков, доступных на страницы. Чтобы его активировать, нужно нажать сочетание клавиш insert + F6
. Для демонстрации работы режима я воспользуюсь им на главной странице Smashing Magazine:


На первом экране отображаются все заголовки страницы. Но также есть возможность переключаться между уровнями заголовков с помощью радиокнопок. Например, я выбрал заголовки четвёртого уровня:

Второй режим помогает пользователям переключаться между заголовками разного уровня. Он активируется с помощью клавиш 1
— 6
. С помощью клавиши 1
JAWS переходит к заголовку первого уровня, и, соответственно, клавиша 6
активирует переход к заголовку 6 уровня. Проиллюстрировать результат работы данного режима я не могу, поэтому в ходе тестирования я опишу, что происходит.
▍ Тестирование
Для первого теста я буду использовать версию разметки с элементами <h1>
, <h2>
и <h3>
:
<body>
<h1>Заголовок первого уровня</h1>
<h2>Заголовок второго уровня</h2>
<h3>Заголовок третьего уровня</h3>
</body>
Проинспектирую страницу с помощью JAWS, нажав сочетание клавиш insert + F6
. В ответ мы увидим следующее окно:

Ожидаемо, JAWS отображает список из трёх заголовков. Один заголовок первого уровня, один второго уровня и один третьего уровня.
Проведём тестирование с помощью клавиш 1
— 3
. Нажимаю клавишу 1
, JAWS говорит: "Заголовок первого уровня, заголовок уровня один". Нажимаю клавишу 2
, JAWS говорит: "Заголовок второго уровня, заголовок уровня два". Нажимаю клавишу 3
, JAWS говорит: "Заголовок третьего уровня, заголовок уровня три".
Хорошо, а теперь создам разметку с использованием атрибутов role
и aria-level
:
<body>
<div role="heading" aria-level="1">Заголовок первого уровня</div>
<div role="heading" aria-level="2">Заголовок второго уровня</div>
<div role="heading" aria-level="3">Заголовок третьего уровня</div>
</body>
После тестирования с помощью JAWS я получил вот такой результат:

Точно такой же список, как и в примере с разметкой с помощью элементов <h1>
, <h2>
и <h3>
.
Посмотрим, что будет при тестировании с помощью клавиш 1
— 3
. Нажимаю клавишу 1
, JAWS говорит: "Заголовок первого уровня, заголовок уровня один". Нажимаю клавишу 2
, JAWS говорит: "Заголовок второго уровня, заголовок уровня два". Нажимаю клавишу 3
, JAWS говорит: "Заголовок третьего уровня, заголовок уровня три". Всё точно так же.
▍ Вывод
На этом этапе мы увидели, что с помощью заголовков скринридеры предоставляют несколько режимов для взаимодействия. Они нацелены на то, чтобы помочь пользователю ориентироваться на странице максимально быстрым способом.
Заключение
Своим исследованием я хотел показать, что при использовании "правильного" или "неправильного" HTML-элемента в разметке, скринридеры автоматически будут использовать "правильную" или "неправильную" роль. Следовательно, от правильного выбора элемента зависит пользовательский опыт людей, использующих их.
Да, мы можем использовать только "неправильный" элемент div
, улучшив его атрибутами role
и другими. Я показал, что это может хорошо работать. Проблема заключается в том, что рано или поздно мы ошибёмся. Да, и честно говоря, я ни разу не видел, чтобы разработчик улучшил диватоз. Обычно все элементы div
остаются на своём месте без изменений.
А это уже напрямую сказывается на пользователях. Они тратят в разы больше усилий на взаимодействие с приложением, чем пользователь без ограничений по здоровью. Я сужу по своим знакомым.
Их жизнь — это целый квест под названием "Разберёмся, как это работает". Я лично хочу им помочь, поэтому я использую максимальное количество HTML-элементов. Надеюсь, вы присоединитесь ко мне. Спасибо за уделённое время. Жду ваше мнение в комментариях.
Telegram-канал с розыгрышами призов, новостями IT и постами о ретроиграх ?️
