Для разработчиков
Помните про семантику и избегайте дивной вёрстки
Семантика важна для вспомогательных технологий и доступности. Она отражает функции, которые выполняют элементы на странице, и делает их поведение более предсказуемым для пользователей.
Не забывайте, что для каждого вида контента есть разные теги, как семантические, так и нет. Про теги можно больше узнать на HTML5 Doctor.
Не путайте кнопки и ссылки
Кнопки
- Фокус с клавиатуры по умолчанию.
- Клик по нажатию на пробел.
- Подсказка для скринридера с помощью
role="button"
. - Состояния
∶focus
,∶hover
,∶active
и∶disabled
. - Блокировка с помощью атрибута
disabled
.
Для чего нужны кнопки:
- отправить данные формы на сервер;
- очистить форму;
- открыть модальное окно или скрытый блок в аккордеоне;
- вызвать всплывающее меню;
- переключить интерфейс;
- проиграть медиа-контент.
Ссылки
- Принимают фокус по умолчанию с помощью атрибута
href=""
. - Клик с помощью клавиши Enter.
- Имеют встроенную роль link.
- Состояния
∶link
,∶visited
,∶focus
,∶hover
и∶active
. - Могут открываться в новых окнах.
- Можно сделать неактивными с помощью
tabindex="-1"
иaria-hidden="true"
.
Для чего нужны ссылки:
- изменить URL и перейти на новую страницу, к окну или к определённой части страницы;
- связать разные части приложения с отрисовкой на клиенте;
- вызвать браузерную перерисовку/перезагрузку.
Ссылка со значением href="#"
, href="javascript:void(0);"
или с другим похожим значением атрибута — уже не ссылка, а кнопка.
Используйте списки
Скринридеры превращают списки в оглавления, с помощью которых пользователи могут быстрее перемещаться по странице.
Где использовать списки:
- для навигации в меню;
- для списка вкладок;
- для списка ссылок. Например, на социальные сети;
- когда обычный текст должен быть списком;
- для списка языков интерфейса, когда их на сайте несколько.
<ul>
<li lang="ru">Русский</li>
<li lang="en">English</li>
</ul>
Не забывайте про атрибут lang=""
Благодаря атрибуту языка скринридеры понимают, на каком языке объявлять контент документа.
Если на странице встречаются слова на языке, отличающимся от основного, то можно оборачивать их в тег <span>
с нужным значением атрибута языка.
<p>Проснувшись однажды утром после беспокойного сна, <span lang="de">Gregor Samsa</span> обнаружил, что он у себя в постели превратился в страшное насекомое.</p>
Добавляйте для каждого тега img атрибут alt
С помощью alt=""
мы:
- описываем содержимое или функции изображений (часть ссылки, кнопка, превью, аватарка);
- называем картинки, которые не загрузились;
- предоставляем поисковым системам контекст картинок вне сайта, на котором они расположены.
Основные правила альтернативного текста
- Текст зависит от контекста.
- Точность и краткость, если это не изображение с большим количеством деталей, например, скриншот.
- Если на картинке есть текст, то его можно использовать в качестве альтернативного.
- Логотип в хедере — название компании или продукта.
- В картинках у кнопок дублируйте её функцию.
<button> <img src="/" alt="Искать по сайту"> <button>
- Не используйте слова «изображение», «картинка». Это дублирует их роль, и скринридер произнесёт два одинаковых слова подряд.
- Для длинных описаний можно использовать
longdesc=""
со ссылкой на страницу с полным описанием картинки, но его поддерживают не все скринридеры. - В конце можно ставить точку, чтобы скринридер делал паузу.

Когда и как использовать атрибут
- Атрибут не нужен для аватарок и декоративных изображений. В этих случаях нужно оставлять его пустым.
- Заворачивайте иконки и текст в одну ссылку. В этом случае
alt=""
не может быть пустым или отсутствовать. - Для изображений в
<figure>
и c<figcaption>
всё равно нужно задать альтернативное описание для картинки.
Соблюдайте иерархию заголовков и используйте на каждой странице один <h1>
Не пропускайте уровни заголовков. Начинайте всегда с <h1
, а за ним размещайте заголовки более низких уровней.
<h1></h1>
<h2></h2>
<h3></h3>
<h4></h4>
<h5></h5>
<h6></h6>
Если у заголовка есть подзаголовки, то тоже соблюдайте правильную иерархию.
<h1></h1>
<h2></h2>
<h3></h3>
<h4></h4>
<h3></h3>
<h4></h4>
<h5></h5>
Добавляйте ссылку с переходом к основному контенту — skip link
Это полезно, когда в меню много пунктов. Такая ссылка поможет пользователям вспомогательных технологий сразу же переходить к основному контенту без утомительного перемещения от первого пункта меню к последнему.
Можно проверить как она работает на сайте The New York Times при навигации с клавиатуры.
Реализацию можно посмотреть в демке на CodePen.
Связывайте поля форм с лейблами или задавайте полям атрибут aria-label
Связывайте <label>
с <input>
при помощи атрибута for=""
.
<label for="input">Лейбл</label>
<input type="text" class="form-control" id="input">
Если в дизайне лейблы к полям не предусмотрены, делайте их скрытыми для обычных пользователей при помощи вспомогательного класса .visually-hidden
.
Ещё один способ описать поле — задать ему атрибут aria-label=""
. Значение атрибута будет доступно только вспомогательным технологиям. Но этот способ подходит для случаев, когда это не полноценная форма, а одиночное поле с кнопкой, например, поиск.
<input type="text" name="search" aria-label="Search">
<button type="submit">Поиск</button>
На способ выше похож способ с aria-labelledby=""
. Значение атрибута также будет доступно только для пользователей вспомогательных технологий. Его стоит применять, когда это одиночное поле с кнопкой.
<input type="text" name="search" aria-labelledby="search-button">
<button id="search-button" type="submit">Поиск</button>
Метод с атрибутом title=""
работает только в случае пользователей, которые не пользуются вспомогательными технологиями. Значение атрибута не доступно для таких технологий, поэтому его не рекомендуется использовать.
Подробнее о лейблах к полям можно узнать из тьюториала W3C.
Используйте title
только тогда, когда это действительно нужно
Атрибут можно использовать для фреймов и иногда для изображений. Но, в большинстве случаев, достаточно aria-label=""
. Есть несколько причин для того, чтобы не использовать title
:
- плохие SEO-практики привели к тому, что вспомогательные технологии и браузеры теперь игнорируют содержимое этого атрибута;
- его содержимое не переводится автоматически;
- не все пользователи поймут, что у элемента есть этот атрибут;
- если контент действительно важен, то его вообще не нужно скрывать, тем более так.
Больше подробностей в статье «The a11y Monthly: Why you shouldn’t rely on the title attribute».
title
для iframe
и frame
В случае фреймов задавайте атрибуту понятное значение.
<iframe src="https://api-maps.yandex.ru/services/inception/..." width="0" height="0" scrolling="no" frameborder="0" ... title="Яндекс.Карты">
Не отменяйте outline
для интерактивных элементов при фокусе
Это важно для пользователей, которые пользуются клавиатурой для навигации по сайту. Просите дизайнеров проработать стили, можно заменить outline
на box-shadow
.
Плохой пример — Яндекс.Маркет. Попробуйте пройти по странице с помощью клавиш.
Хороший пример — сайт Xbox.
Увеличивайте область клика с помощью padding
Оптимальный размер кликабельной области — 48×48 px.
Особенно это важно делать в меню. Между пунктами меню не должно быть неактивных зазоров, поэтому задавайте одинаковые padding
для ссылок слева и справа от них. Для последних и первых можно отменить отступ слева или справа соответственно.
Используйте ARIA-роли только тогда, когда это действительно нужно
- Лучше никакой ARIA, чем плохая ARIA.
- Если используете ARIA, то не дублируйте уже встроенные в элементы роли.
role="none"
и role="presentation"
Обе роли выполняют одинаковую функцию — отменяют семантику элемента.
ARIA 1.1: «До тех пор, пока не будет хорошо поддерживаться role="none"
, рекомендуется использовать только role="presentation"
или избыточный вариант с фоллбеком role="none presentation"
».
Можно использовать при табличной вёрстке. Чтобы смягчить негативные последствия такого выбора, у таблиц можно удалить семантическое свойство при помощи role="presentation"
для элемента table
. Это сделает такой контент более понятным для пользователей скринридеров.
Можно использовать для прогрессивного улучшения разметки, если JavaScript недоступен, и при приведении разметки в соответствие с требованиями ARIA. Например, для панели вкладок.
<ul role="tablist">
<li role="presentation">
<a href="#panel_1"
role="tab"
aria-selected="true/false"
aria-controls="panel_1">
</a>
</li>
</ul>
Подробнее в статье Скотта О’Хары «Know your ARIA: 'Hidden' vs 'None'».
aria-label
Этот атрибут используется для элементов без текстового содержимого. Например, в ссылках на иконочных шрифтах, в ссылках-изображениях и в кнопках без текста. Сами иконки скрываются от вспомогательных технологий при помощи aria-hidden="true"
.
<a href="{{this.url}}" target="_blank" class="socials__link" title="{{this.title}}" aria-label="{{this.title}}">
<i class="fa fa-{{@key}}" aria-hidden="true">
</a>
- В атрибуте кратко описывайте то, что делает кнопка или ссылка.
- Атрибут не переводится сервисами автоматического перевода.
Отсутствие текста у кнопок и ссылок — критическая ошибка.
aria-labelledby
Атрибут создаёт связь между объектами и их метками.
Вспомогательные технологии используют его, чтобы собирать все метки в каталог документа, из которого пользователь может перемещаться между ними.
Можно использовать атрибут в дополнение к элементам форм, чтобы связать статический текст с виджетами, группами элементов, панелями, областями, которые имеют заголовок, определения и другие типы объектов.
Несколько значений атрибута перечисляются через пробел.
Пример с несколькими лейблам:
<div id="billing">Биллинг</div>
<div>
<div id="name">Имя</div>
<input type="text" aria-labelledby="billing name"/>
</div>
<div>
<div id="address">Адрес</div>
<input type="text" aria-labelledby="billing address"/>
</div>
Пример с группой переключателей:
<div id="radio_label">Переключатели</div>
<ul role="radiogroup" aria-labelledby="radio_label">
<li role="radio">Пункт 1</li>
<li role="radio">Пункт 2</li>
<li role="radio">Пункт 3</li>
</ul>
Больше примеров использования можно найти в статье про aria-labelledby
на MDN.
Делайте интерактивные области Live Region
Если на странице есть часть, содержимое которой изменяется, то нужно сделать её live region. Тогда скринридеры смогут держать своих пользователей в курсе всех изменений.
Сделать такую часть страницы интерактивной можно с помощью нескольких ролей.
role="alert"
— важные ошибки, предупреждения. Для большей совместимости добавляйте её к нужным элементам вместе с атрибутом aria-live="assertive"
.
aria-live=""
— атрибут для определения срочности сообщения об изменениях. Там, где об изменениях не нужно объявлять, используйте aria-live="off"
. В большинстве случаев не нужно срочно сообщать об изменениях, поэтому в них пригодится aria-live="polite"
. Иногда, когда речь идёт о важном сообщении, например, серверной ошибке, можно использовать aria-live="assertive"
.
role="status"
— сообщения о менее важных ошибках и предупреждениях. Например, сообщение об автосохранении, неправильно заполненном поле и тому подобном. Для совместимости следует сочетать эту роль с атрибутом aria-live="polite"
.
role="log"
— история сообщений, список ошибок и другое, где важна последовательность обновления информации. Для большей совместимости используйте вместе с ней атрибут aria-live="polite"
.
role="timer"
— таймер, счётчик или секундомер. Не забудьте об aria-live="off"
для лучшей совместимости.
Подробнее о ролях и значениях атрибута aria-live
в статье «Всё, что нужно знать про ARIA Live Regions».
Учитывайте какие CSS-свойства попадают в дерево доступности
Их не так много:
display: none
иdisplay: block
.visibility: hidden
,visibility: collapse
(для строк и ячеек таблиц) иvisibility: visible
.list-style: none
(в Safari).
list-style: none
В Safari этот атрибут отменяет семантику списков.
Если важно сохранить семантику списка во всех браузерах, то есть три варианта решения.
Первый вариант — явно задать роль для тегов <ul>
или <ol>
с помощью атрибута role="list"
. Однако WAI-ARIA не рекомендует дублировать роли элементов.
Можно использовать пробел нулевой ширины.
.list li {
list-style-type: none;
}
.list li::before {
content: "\200B";
position: absolute;
}
Наконец, есть хак с url(#!)
.
ul {
list-style: none;
}
ol, ul {
list-style: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'/%3E");
}
Этот хак может привести к появлению лишнего отступа сверху у элементов навигации в IE11 и Edge 42.
Думайте о том, как лучше скрыть элемент
Учтите, важен ли элемент для пользователей, в том числе для тех, кто пользуется скринридерами. Есть несколько возможных сценариев:
- всем пользователям нужен элемент;
- ни обычным пользователям, ни пользователям вспомогательных технологий не нужен элемент;
- элемент нужно оставить на странице, но скрыть от вспомогательных технологий;
- элемент нужно убрать со страницы, но оставить его доступным для вспомогательных технологий.
В зависимости от сценария выберите подходящий метод скрытия элемента.
display: none;
: элемент не попадает в дерево доступности, скрыт от вспомогательных технологий и пользователей. Работает везде.
Атрибут hidden
: элемент не попадает в дерево доступности, скрыт от вспомогательных технологий и пользователей. Не работает в версиях IE, ниже 11. Лучше делать фоллбек с помощью display: none;
.
visibility: hidden;
: элемент не попадает в дерево доступности, скрыт от вспомогательных технологий и пользователей. Работает везде.
aria-hidden="true"
: неинтерактивный элемент не попадает в дерево доступности и скрыт от вспомогательных технологий. Другие пользователи видят элемент. Не работает в версиях IE, ниже 11.
Класс .visually-hidden
или .vh
: элемент попадает в дерево доступности и к нему имеют доступ вспомогательные технологии. Другие пользователи не видят элемент. Работает везде.
alt=""
: скрывает картинку из дерева доступности. Другие пользователи видят изображение. Работает везде.
Класс .visually-hidden
или .vh
.visually-hidden {
position: absolute;
left: 0;
padding: 0;
list-style: none;
height: 1px;
width: 1px;
overflow: hidden;
clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
clip: rect(1px, 1px, 1px, 1px);
}
body:hover .visually-hidden a,
body:hover .visually-hidden input,
body:hover .visually-hidden button {
display: none !important;
}
aria-hidden=""
aria-hidden="true"
удаляет элемент из дерева доступности, но не скрывает на странице.aria-hidden="false"
возвращает элемент в дерево доступности.
Используйте атрибут тогда, когда элемент декоративный, дублирующийся или эквивалентный тому, который уже есть на странице. Например, если у вас есть иконочный шрифт.
<a href="/">
<span class="font-icon font-icon--home" aria-hidden="true"></span>
Главная
</a>
Избегайте автовоспроизведения видео и фоновых медиа
Во-первых, это раздражает, во-вторых, вызывает чувство тревоги и даже паники у некоторых пользователей.
Золотое правило медиа-контента: дать пользователям возможность самим управлять им.