Оглавление
Доступность
Атрибут языка
Для элемента <html> в атрибуте lang должен указываться соответствующий язык документа. Это помогает инструментам синтеза речи определить, какое использовать произношение или системам перевода, какие использовать языковые правила.
<!DOCTYPE html>
<html lang="ru">
<head>…</head>
<body>…</body>
</html>
Доступное скрытие
Для того чтобы контент был скрыт от глаз, но доступен для скринридеров и поисковиков его нужно скрывать используя утилитарный класс visually-hidden.
/* 💩 Плохо: скрывать элемент с помощью font-size, display:none */
h1 {
font-size: 0;
}
.title {
display: none;
}
/* 😊 Хорошо: использован класс visually-hidden */
.visually-hidden {
position: absolute;
width: 1px;
height: 1px;
margin: 0;
padding: 0;
overflow: hidden;
white-space: nowrap;
border: 0;
clip: rect(0 0 0 0);
-webkit-clip-path: inset(50%);
clip-path: inset(50%);
}
/* 😊 Хорошо: использован миксин visually-hidden из хелперов @maxus/themes */
@include visually-hidden()
/* <h2 class="visually-hidden">Заголовок</h2> */
Атрибут alt
Обязательно нужно указывать атрибут alt у тега img, чтобы помочь слепым и слабовидящим пользователям понять, что изображено на картинке. Описание зависит от типа изображения — информативное, график или диаграмма, декоративное и группа изображений.
/* 💩 Плохо: атрибут не задан */
<img src="img/picture.png" alt="">
/* 😊 Хорошо: атрибут alt задан */
<img src="dog.png" alt="Собака-проводник с колокольчиком на шее">
Декоративные изображения
Если изображения служат только для декораций и нужно чтобы скринридеры их игнорировали, то можно добавлять их с помощью свойства CSS background-image. Либо следует использовать атрибуты role="presentation" и aria-hidden="true".
/* 💩 Плохо: скринридер попытается описать картинку, скорее всего это будет имя файла */
<img src="gradient.png" />
/* 😊 Хорошо: скринридер проигнорирует картинки, так как для незрячего человека они не несут никакой ценности */
<img src="gradient.png" aria-hidden="true" alt="">
<div style="background-image: url(./images/gradient.png)"></div>
Группы изображений
Для групп изображений, которые представляют одну и ту же информацию, например, звездочки рейтинга, добавьте описание в alt только к первому изображению.
<img src="star-full.png" alt="Рейтинг фильма 4 из 5" />
<img src="star-full.png" alt="" />
<img src="star-full.png" alt="" />
<img src="star-full.png" alt="" />
<img src="star-empty.png" alt="" />
Старайтесь не менять ARIA-ролями поведение семантических элементов
Каждый HTML-элемент имеет свой смысл и назначение.
Если используется button, то устройства понимают, что это интерактивный элемент, с которым можно взаимодействовать с помощью мыши, клавиши Enter или пробела. В случае a — что взаимодействие приведет к переходу на другую страницу. Не стоит менять это поведение.
/* 💩 Плохо: подмена роли */
<h1 role="button" @click="...">Кликабельный заголовок</h1>
/* 😊 Хорошо: семантичный HTML */
<h1><button @click="...">Кликабельный заголовок</button></h1>
Интерактивные элементы должны быть хорошо проработаны
Недостаточно просто добавить ARIA-роль для элемента. Например, если кнопка реализуется с помощью тэга <div>, а не <button>, то следует вручную реализовать такое же поведение, как у нативной кнопки.
В руководстве ARIA указан список возможностей и поведение, которым должен обладать каждый элемент.
Создание элемента, выглядящего как кнопка, не делает его кнопкой. Правильная кнопка должна удовлетворять следующим требованиям:
- Должна быть кликабельной с помощью курсора
- Должна быть кликабельной с помощью клавиши Enter
- Должна быть кликабельной с помощью клавиши пробела
/* 💩 Плохо: интерактивный элемент не проработан*/
<div @click="onClick"></div>
/* 😊 Хорошо: интерактивный элемент соответствует ARIA */
<div
tabindex="0"
role="button"
@click="onClick"
>
</div>
/* 😊 Хорошо: семантичный элемент */
<button
type="button"
@click="onClick"
></button>
Описывайте интерактивные элементы
Элементы, с которыми можно взаимодействовать, например кнопки и ссылки, должны иметь описание, позволяющее понять, что эти элементы делают.
/* 💩 Плохо: нет привязанного лейбла */
<input type="text" placeholder="Имя пользователя">
/* 😊 Хорошо: инпут с лейблом */
<label>
Имя пользователя
<input type="text">
</label>
/* 😊 Хорошо: инпут с лейблом по id */
<label for="password">Пароль</label>
<input type="password" id="password">
Аудио и видео
Чтобы помочь пользователям с нарушениями зрения воспринять аудио или видео контент — следует добавлять описание. Это поможет таким пользователям узнать, о чем говорится в ролике или в аудио. Если у видео есть визуальная информация, которая не озвучена, добавьте аудиоописание.
-
Для медиаконтента с длинным описанием можно использовать атрибуты
aria-describedby,longdescили невидимый для обычного пользователя блок с информацией. -
Для аудиозаписей или видео со звуком добавьте альтернативное текстовое описание в атрибуты
aria-describedby,longdescили ссылку на страницу с альтернативным описанием. Если в аудиозаписи есть диалог, укажите, кто именно говорит. -
Для видео без звука к самому файлу добавьте краткое описание, отдельно добавьте длинное описание с помощью атрибутов
aria-describedby,longdesc.
<h1>
Ноутбук Apple MacBook Pro 16" Core i7 2,6 ГГц, 16 ГБ, 512 Гб SSD, AMD Radeon Pro 5300M, Touch Bar (серый космос)
</h1>
<iframe
aria-describedby="video-description"
src="https://www.youtube.com/watch?v=3l6X7cG7Abo"
frameborder="0"
width="640"
height="360"
allow="autoplay"
></iframe>
<p id="video-description">
Обзор MacBook Pro 16" — тесты, игры, сравнение с 15"
</p>
Навигация
Удобная и понятная навигация поможет не только слепым, но и всем остальным пользователям свободно перемещаться по сайту и знать текущее положение.
Для верстки меню используйте элемент nav. Если последовательность пунктов меню важна, используйте упорядоченный список ol, а если нет — список ul.
Чтобы пользователь мог понять назначение меню, добавьте заголовок с помощью атрибутов aria-label или aria-labelledby.
Для текущего пункта меню удалите ссылку, добавьте атрибут aria-current="page" и невидимый текст, например «Текущий пункт: ».
Если меню многоуровневое — добавьте к родительскому пункту атрибут aria-haspopup="true" и правильно настройте роли для дочерних элементов.
<nav aria-label="О компании">
<ul>
<li aria-current="page">
<span><span class="hidden">Текущий пункт:</span>О нас</span>
</li>
<li><a href="#">Примеры работ</a></li>
<li><a href="#">Контакты</a></li>
</ul>
</nav>
Таблицы
Для того чтобы сделать доступными данные, представленные в табличном виде — старайтесь верстать их с помощью элемента <table>. В случае, когда <table> не отвечает вашим требованиям — не забывайте правильно расставлять ARIA-роли для соответствующих элементов.
Для заголовка таблицы используйте элемент <caption> или атрибуты aria-describedby и aria-label.
Используйте атрибут scope для связывания между собой заголовков ячеек и ячеек с данными.
<table>
<caption>Список студентов курса</caption>
<thead>
<tr>
<th scope="col">№ строки</th>
<th scope="col">ФИО</th>
<th scope="col">Дата рождения</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">1</th>
<th>Иванов Иван Иванович</th>
<th>01.01.2000</th>
</tr>
</tbody>
</table>
<div role="table" aria-label="Студенты" aria-describedby="students-table-desc">
<div id="students-table-desc">
Список студентов курса
</div>
<div role="rowgroup">
<div role="row">
<span role="columnheader">
№ строки
</span>
<span role="columnheader">
ФИО
</span>
<span role="columnheader">
Дата рождения
</span>
</div>
</div>
<div role="rowgroup">
<div role="row">
<span role="rowheader">
1
</span>
<span role="cell">
Иванов Иван Иванович
</span>
<span role="cell">
01.01.2000
</span>
</div>
</div>
</div>
Управление с клавиатуры
Доступный интерфейс должен позволять перемещаться по нему и управлять им не только мышью, но и с помощью клавиатуры — листать страницу, переходить по ссылкам, заполнять формы и т.д.
Правильная организация перехода фокуса на странице даст возможность перемещаться по странице с помощью скринридеров.
1. Соблюдайте порядок
Пользователь ожидает, что фокус будет переключаться между элементами в логичном порядке — обычно слева направо и сверху вниз. Используйте tabindex="-1", чтобы пропустить элемент, и tabindex="0", чтобы сделать элемент доступным для фокуса.
2. Не скрывайте фокус
Очень часто разработчики скрывают фокус с помощью outline: none или tabindex=-1, т.к. им не нравится внешний вид или то, что фокус виден при клике мышкой.
Из-за этого пользователи теряют возможность управлять интерфейсом с помощью клавиатуры — становится не понятно, какой элемент сейчас активный.
Вместо этого — стилизуйте фокус и, если нужно, делайте его видимым только при управлении с клавиатуры.
3. Обеспечьте понятное управление
При разработке интерактивных компонентов, например табов, меню и т.д. — старайтесь придерживаться общепринятой логики управления.
Это поможет всем без исключения пользователям вашего сайта легко и быстро начать использовать интерфейс.
/* 💩 Плохо: скрыт outline */
<style>
.btn {
outline: none;
}
</style>
/* 💩 Плохо: нарушен порядок индексов */
<button tabindex="1"></button>
Уведомляйте пользователей об ошибках, шагах и успехе
После отправки формы — выводите понятные и краткие уведомления об ошибках и успехе. Так пользователи смогут лучше понять, что произошло после отправки формы.
<form>...</form>
<!-- assertive - сообщение будет прочитано немедленно -->
<!-- polite - сообщение будет озвучено после текущего -->
<div role="alert" aria-live="assertive">
Ваши настройки не сохранились, попробуйте ещё раз!
</div>
<label>
Адрес:
<input name="address" type="text" aria-describedby="address-error">
</label>
<div id="address-error">
Введите корректный адрес
</div>