Я продолжаю рассказывать, как HTML и CSS могут улучшить или ухудшить доступность интерфейсов. В своём рассказе я использую свой опыт и моего незрячего знакомого Ильи. Мы уже выпустили первую часть.


В этой статье будет: атрибут autofocus и его нюансы, паттерн «Skip-link» и идея Ильи об использовании его на практике, проблема использования одинаковых ссылок для одной новости, что не так с кнопкой «Наверх» и как вы спрятали список от скринридеров.


Давайте начнём!


▍ Атрибут autofocus помогает пользователям не делать лишний путь перед заполнением данных формы


Когда главная задача веб-страницы предоставить пользователю форму для заполнения данных, мы можем спасти тех, кто использует клавиатуру и скринридер от пары десяток нажатий клавиши Tab или свайпов. Нам поможет атрибут autofocus. Достаточно добавить его для первого элемента input, с которого пользователь должен начать заполнение формы.


Например, такой паттерн можно увидеть на сайте Github при авторизации. Для примера я удалил ненужные атрибуты:


<form>
  <label for="login_field">Username or email address</label>
  <input type="text" id="login_field" autofocus="autofocus">
  <div class="position-relative">
    <label for="password">Password</label>
    <input type="password" id="password">
    <input type="submit" value="Sign in">
    <a href="/password_reset">Forgot password?</a>
  </div>
</form>

В этом примере мы можем сразу вводить логин или почту без дополнительных действий. Очень простой трюк, а делает жизнь пользователя проще. Но есть одно «но».


При использовании атрибута важно учитывать контекст, в котором находился пользователь до момента перехода к форме. Если упустить этот нюанс, то пользователь может запутаться. Опыт Ильи:


«Если это результат нажатия ссылки, находясь на сайте, тогда автоматический фокус к первому полю ввода однозначно упрощает жизнь. А вот если такая ссылка размещена на стороннем ресурсе или в документе, я бы поостерёгся сразу заполнять. Всегда опасаюсь внешних ссылок и стараюсь сначала осмотреться, прочитав хотя бы шапку».


Так что сначала анализируем путь до формы, если он выглядит безопасным, то смело используем атрибут autofocus.


▍ Паттерн «Skip-link» даёт пользователям быстрый доступ к основным разделам страницы


Для пользователей скринридера и клавиатуры клавиша Tab является основным способом взаимодействия с интерфейсом. Они сотни раз за день жмут её. Соответственно, наша задача упростить им взаимодействие. И здесь на помощь приходит паттерн «Skip link» или «скип-линк».


Суть паттерна заключается в том, что мы создаём внутренние ссылки на основные области страницы, которые визуально отображаются только при попадании на них с помощью клавиши Tab. Самым распространённым примером является ссылка «Перейти к основному контенту». Илья считает её важнейшим элементом на странице. Вот что он говорит:


«Ссылка для перехода к основному контенту очень важный элемент, который может быть на странице для ускорения просмотра. Особенно при просмотре большого количества страниц с повторяющимися элементами вроде шапки, навигации и так далее. Главное, чтобы она приводила к началу основной области. Ещё она должна быть первым элементом на странице.»


Как реализовать паттерн? Разберём на примере ссылки «Перейти к основному контенту». Как сказал Илья, важно, чтобы ссылка была первым элементом на странице. Так, что её надо расположить после элемента <body>. Таким образом, после загрузки страницы пользователь нажимает Tab и сразу попадает на ссылку и сможет перейти к основному контенту.


<body>
  <a href="#main-heading" class="show-on-focus">Перейти к основному контенту</a>
  <nav>
    <ul>
      <li><a href="/home">Главная</a></li>
      <li><a href="/about">Обо мне</a></li>
      <li><a href="/contacts">Контакты</a></li>
    </ul>
  </nav>
  <main>
    <h1 id="main-heading">Главный заголовок</h1>
    <!-- здесь основное содержимое страницы -->
  </main>
</body>

Главное CSS требование для паттерна — нельзя использовать display: none, потому что тогда пользователь не сможет попасть на ссылку клавиатурой или скринридером. А так подходит любой доступный способ для скрытия элемента. Я покажу реализацию Github:


.show-on-focus {
  position: absolute !important;
}
 
.show-on-focus:not(:focus) {
  width: 1px !important;
  height: 1px !important;
  padding: 0 !important;
  overflow: hidden !important;
  clip: rect(1px, 1px, 1px, 1px) !important;
  border: 0 !important;
}

У Ильи есть ещё одна идея, где можно использовать этот паттерн. Вот она:


«У меня есть ещё одна идея. Я нигде её не видел, но опытным путём понял, что она была бы мне полезна. Обычно делают кнопку „Наверх“, которая приводит в шапку. По сути, это дублирование клавиши PageUp. Мне же было бы удобно, чтобы она располагалась последним элементом в области основного контента и приводила в меню. Это очень здорово помогало бы просматривать страницу за страницей.»


Мне кажется, она очень полезной. Да, и сделать её просто. Надо расположить ссылку в конце элемента <main>.


<body>
  <a href="#main-heading" class="show-on-focus">Перейти к основному контенту</a>
  <nav id="navigation">
    <ul>
      <li><a href="/home">Главная</a></li>
      <li><a href="/about">Обо мне</a></li>
      <li><a href="/contacts">Контакты</a></li>
    </ul>
  </nav>
  <main>
    <h1 id="main-heading">Главный заголовок</h1>
    <!-- здесь основное содержимое страницы -->
    <a href="#navigation" class="show-on-focus">Вернуться к меню</a>
  </main>
</body>

▍ Использование одинаковых ссылок приводит к увеличению количества взаимодействий с интерфейсом


Вёрстка блока новостей кажется простой задачей, но на самом деле это не так. Рассмотрим код блока статьи из сайта, который я недавно аудировал:


<div class="news-main_item ">
  <a href="/news/">
    <img src="f901a.jpg" alt="Более 150 вылетов совершили вертолёты санитарной авиации с начала 2023 года">
  </a>
  <a href="/news/">
    <span class="news-title">Более 150 вылетов совершили вертолёты санитарной авиации с начала 2023 года</span>
  </a>
  <span class="news-text">В медучреждения были эвакуированы 133 пациента в тяжёлом состоянии</span>
  <p>
    С начала 2023 года вертолёты ...
  </p>             
</div>

Мой скринридер JAWS обрабатывает этот код вот так. Сначала он переходит к первой ссылке и говорит: «Ссылка графика. Более 150 вылетов совершили вертолёты санитарной авиации с начала 2023 года». Далее он переходит ко второй ссылке: «Ссылка. Более 150 вылетов совершили вертолёты санитарной авиации с начала 2023 года». Далее озвучивается оставшиеся текст из элементов span и p.


В чём здесь проблема? Проблема заключается в том, что пользователи скринридера и клавиатуры вынуждены сначала фокусироваться на первую ссылку, а потом на вторую. А они ведут на одну и туже страницу! Таким образом, для пользователя в два раза увеличивается количество взаимодействий с интерфейсом без какой-либо пользы для него.


Как можно исправить ошибку? Я буду исходить из того, что при клике по изображению пользователь должен переходить по адресу ссылки. Так, что я предлагаю переместить его в ссылку.


<div class="news-main_item ">
  <a href="/news/">
    <img src="f901a.jpg" alt="">
    <span class="news-title">Более 150 вылетов совершили вертолёты санитарной авиации с начала 2023 года</span>
  </a>
  <span class="news-text">В медучреждения были эвакуированы 133 пациента в тяжёлом состоянии</span>
  <p>
    С начала 2023 года вертолёты ...
  </p>             
</div>

Также я убрал текст из атрибута alt. Зачем так делать я описал в первой части. Предвидя вопросы, я сразу скажу, что визуально элементы располагаются в столбец. Соответственно, мои изменения не повлияют на отображение. Но как быть в случае, когда изображение находится в одной колонке, а остальные элементы во второй?


В этом случае разметка должна быть такой же с одной ссылкой. А колонки можно реализовать с помощью CSS Grids или абсолютного позиционирования. Если честно, с точки зрения доступности неважно каким способом сделаны колонки. Нам важно избежать дублирования ссылок.


▍ Кнопка «Наверх» не первый элемент на странице


При аудировании сайтов одним из распространённых ошибок является положение кнопки «Наверх» в коде. Обычно она находится перед основными элементами в самом начале странице вот так:


<body>
  <button type="button" aria-label="Перейти к началу страницы">
    <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 26 26">
      <polyline stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" points="19 11 13 5 7 11"></polyline>
      <path d="M13 5 L13 21" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
    </svg>
  </button>
  <!-- код для основной страницы -->
</body>

Почему это плохо? Я пользователь клавиатуры. После загрузки страницы нажимаю клавишу Tab и попадают кнопку наверх. Так я уже наверху! Я не посмотрел сайт. Зачем мне эта кнопка? А ещё отдельный прикол, когда её скрывают визуально. А я сижу и думаю: «Куда у меня фокус делся?». У Ильи похожее мнение, потому что ему ридер после загрузки страницы говорит: «Наверх, кнопка». Мне кажется, что очевидно, что он ничего не понял.


Для исправления этой ошибки нужно сделать три действия. Выделить код кнопки. Вырезать. Вставить в конец страницы перед закрывающим тегом <body>, чтобы кнопка стала последним элементом.


<body>
  <!-- код для основной страницы -->
  <button type="button" aria-label="Перейти к началу страницы">
    <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 26 26">
      <polyline stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" points="19 11 13 5 7 11"></polyline>
      <path d="M13 5 L13 21" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
    </svg>
  </button>
</body>

list-style: none прячет список от скринридера


Общаясь с незрячими людьми, я понял, список — одна из полезнейших структур. Он даёт дополнительную информацию о количестве элементов, между пунктами можно быстро переключать или выйти из него, не проходя все дочерние элементы. К сожалению, свойство list-style может незаметно отменить его.


Все фронтендеры писали list-style: none, чтобы сбросить маркеры списка.


<ul class="list">
  <li>элемент 1</li>
  <li>элемент 2</li>
  <li>элемент 3</li>
</ul>

.list {
  list-style: none;
}

Всё. После этого некоторые скринридеры не смогут определить список. Вся функциональность потеряна. Как исправить? Здесь поможет атрибут role. С помощью него мы снова скажем скринридеру, что данная структура — это список.


<ul role="list" class="list">
  <li>элемент 1</li>
  <li>элемент 2</li>
  <li>элемент 3</li>
</ul>

▍ Заключение


С помощью этой статьи я с Ильёй хотел призвать вас:


  • Использовать атрибут autofocus на страницах для заполнения форм;
  • Сделать ссылки на основные области страницы с помощью паттерна «Skip-link»;
  • Не создавать ссылки с одинаковыми путями;
  • Проверить позицию интерактивных элементов, которые визуально скрыты и появляются в какой-то момент;
  • Добавить role="list" к спискам, к которым объявлено list-style: none.

Также нам будет интересен и ваш опыт. Делитесь своими кейсами в комментариях. Ещё оставляю ссылку на первую часть. Спасибо за чтение.


Узнавайте о новых акциях и промокодах первыми из нашего Telegram-канала ????

Комментарии (2)


  1. Dolios
    26.10.2023 08:07

    А зачем так?

    <input type="text" id="login_field" autofocus="autofocus" />
    

    Это же булевый атрибут, должно быть достаточно вот так:

    <input type="text" id="login_field" autofocus />
    


    1. melnik909 Автор
      26.10.2023 08:07

      Я хотел максимально сохранить оригинальный код и копировал из DevTools. Там autofocus="autofocus"