Оглавление

    Доступность

    Атрибут языка

    Для элемента <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>