Я продолжаю рассказывать, как 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
.
Также нам будет интересен и ваш опыт. Делитесь своими кейсами в комментариях. Ещё оставляю ссылку на первую часть. Спасибо за чтение.
Автор: Стас Мельников