Хабр, я снова пришёл к вам с практическими советами про доступность вместе с Ильёй. Мы показываем, как HTML и CSS могут улучшить или ухудшить её. Напоминаю, что Илья мой незрячий знакомый, который помогает мне найти наши косяки в вёрстке.
Сегодня мы рассмотрим следующие аспекты:
- какие есть проблемы со ссылкой «Подробнее»;
- важно ли явно связывать элементы
<label>
и<input>
с помощью атрибутовid
иfor
при вёрстке чекбоксов; - существующие нюансы при озвучке чисел.
Давайте начнём!
▍ Что можно сделать с паттерном «Подробнее»
Во второй части серии я рассказывал, почему нам стоит избегать дублирующих друг друга ссылок. К сожалению, не всегда можно их избежать. Сегодня до сих пор популярен паттерн «Подробнее».
Что я имею в виду? Лично я встречал две его реализации. Первая выглядит как ссылка с текстом. Например, «Подробнее», «см. далее», и так далее.
Вторая реализация выглядит как ссылка в виде иконки. Например, иконка со стрелкой вправо.
Мы как разработчики можем сделать несколько вещей, чтобы улучшить опыт пользователей. Первое — это сказать дизайнеру, что это уже «не модно». В интернете есть множество статей, рассказывающие, почему данный паттерн избегают. Но что делать, если дизайнер упёрся и не хочет ничего менять? Я предлагаю несколько вещей.
Начнём мы с менее радикального. Проблема ссылки «Подробнее» в том, что она не информативна. Она такая для всех. Только зрячие пользователи могут быстро визуально взять дополнительную информацию из окружающих элементов (контекста). Пользователи скринридера так не могут. Я показал Илье пример, и вот, что он сказал:
«Когда я встречаю ссылку «подробнее», мне нужно быть уверенным, что она ведёт на страницу, которую я ожидаю. Для этого мне приходится возвращаться назад к предыдущим элементам, чтобы понять контекст. В твоём примере я вернулся назад, чтобы перечитать условия кредита и убедиться, что ссылка ведёт на страницу с подробными условиями по кредиту».
Илья буквальной идёт до заголовка блока, где находится ссылка. С помощью него и другой информации он понимает, чего ждать от перехода по ссылке. Как мы можем ему помочь?
Ответ мы рассмотрим на первом примере. Только я упрощу разметку.
<body>
<div class="kUl5hC">
<h2 class="aR7Oy1">
<a href="/get-money/credit/credit-cash/">Кредит наличными</a>
</h2>
<div class"kUl5hC">
<!-- здесь краткая информация о кредитном продукте -->
</div>
<div class="aUl5hC">
<a href="/get-money/credit/credit-cash/">Подробнее</a>
<a href="/get-money/credit/credit-cash-adv/step1/?platformId=alfasite">Оформить заявку</a>
</div>
</div>
</body>
Посмотрим на заголовок. Текст в нём вполне информативный. Почему бы его не вставить прямо в ссылку перед текстом «Подробнее». Тогда скринридеры скажут: «Кредит наличными. Подробнее. Ссылка». Только надо не забыть скрыть текст с помощью паттерна visually-hidden
.
<body>
<div class="kUl5hC">
<h2 class="aR7Oy1">
<a href="/get-money/credit/credit-cash/">Кредит наличными</a>
</h2>
<div class"kUl5hC">
<!-- здесь краткая информация о кредитном продукте -->
</div>
<div class="aUl5hC">
<a href="/get-money/credit/credit-cash/">
<span class="visually-hidden" role="presentation">Кредит наличными.</span>
Подробнее
</a>
<a href="/get-money/credit/credit-cash-adv/step1/?platformId=alfasite">Оформить заявку</a>
</div>
</div>
</body>
.visually-hidden {
clip-path: inset(50%);
height: 1px;
overflow: hidden;
position: absolute;
white-space: nowrap;
width: 1px;
}
Для пользователей скринридера мы уменьшили ментальную нагрузку. А вот обо мне не подумали. Поскольку я переключаюсь по интерфейсу клавишей Tab
, то мне придётся дважды попадать на одну и ту же ссылку. Если вы хотите упростить мне жизнь, то рассмотрим следующий способ.
Мы можем скрыть ссылку с помощью атрибута aria-hidden
и значения true
. Также нужно не забыть отключить интерактивность с помощью атрибута tabindex
и значения -1
.
<body>
<div class="kUl5hC">
<h2 class="aR7Oy1">
<a href="/get-money/credit/credit-cash/">Кредит наличными</a>
</h2>
<div class"kUl5hC">
<!-- здесь краткая информация о кредитном продукте -->
</div>
<div class="aUl5hC">
<a href="/get-money/credit/credit-cash/" aria-hidden="true" tabindex="-1">Подробнее</a>
<a href="/get-money/credit/credit-cash-adv/step1/?platformId=alfasite">Оформить заявку</a>
</div>
</div>
</body>
У вас может возникнуть вопрос — зачем мы используем атрибут aria-hidden
, если мы помогаем пользователям клавиатуры? Всё дело в том, что пользователи скринридера тоже используют клавиатуру.
Если мы добавим только атрибут tabindex
, они не смогут попасть на элемент клавишей Tab
. Но! Они попадут на него клавишами стрелок. Это их только запутает. Они будут думать, почему одним способом получилось попасть, а другим нет. По этой причине нам нужны оба атрибута.
Напомню, что этот способ считается хаком. Лучше его избегать. Но если ваш дизайнер не хочет убирать ссылку «Подробнее», то можно использовать моё решение. Только, пожалуйста, приложите все силы, чтобы дизайнер всё же её убрал.
Также если вы не знаете про атрибут aria-hidden
, вы можете прочитать мою статью.
▍ Можно ли элементом label
сломать озвучку чекбокса
Недавно лазил по сайту известного банка со скринридером NVDA и нашёл интересный баг, связанный с нестандартными чекбоксами. При переключении с помощью клавишей стрелок вверх и вниз текст, связанный с чекбоксом, озвучивался после повторного нажатия по клавише.
Конечно, я полез копаться в коде. Я скажу, что на первый взгляд всё было хорошо. Даже был элемент <label>
. Только разработчики приложения используют его, как обвёртку для элемента <input>
. Другими словами, они создают неявную связь элементов.
<body>
<label class="custom-cb">
<input type="checkbox">
<span>Соглашаюсь с правилами</span>
</label>
</body>
При тестировании примера с помощью переключения клавишей со стрелкой вниз я сначала услышал: «Флажок. Не отмечено». Нажав второй раз клавишу, скринридер NVDA добавил текст «Соглашаюсь с правилами».
Я сразу решил проверить, чтобы будет, если явно связать элементы <input>
и <label>
через атрибуты id
и for
.
<body>
<div class="custom-cb">
<input type="checkbox" id="cb-2">
<label for="cb-2">Соглашаюсь с правилами</label>
</div>
</body>
Случилась магия. Скринридер сразу стал озвучивать всю подсказку вместе с текстом. Я услышал: «Флажок. Не отмечено. Соглашаюсь с правилами».
Не знаю, давно ли такое поведение. Я обычно использовал явную связь элементов <input>
и <label>
. Но если у вас используется неявная, то я рекомендую вам проверить её скринридером NVDA. Эта ошибка не критична, но всё равно немного ухудшает пользовательский опыт. Пожалуйста, исправьте её.
▍ Скринридеры не дружат с большими числами
Числа — неотъемлемая часть интерфейсов. Изучая тему доступности, естественно, мне было интересно, есть ли проблемы с их озвучкой. Сразу скажу, они есть. И я лично не знаю, как их разрешить. Но всё по порядку. Я провёл пару тестов. Их хочу показать вам.
Первым нашим тестом будет знак пробела, который используется для разделения разрядов в числе. Мы посмотрим, как скринридеры NVDA и JAWS озвучат текст «24 682₽ за ночь». Результат записан в комментариях в коде. Начнём с версии, где есть пробел.
<body>
<!-- NVDA. В браузерах Chrome и Firefox. Двадцать четыре шестьсот восемьдесят два рубль за ночь -->
<!-- JAWS. В браузерах Chrome и Firefox. Двадцать четыре тысячи шестьсот восемьдесят два знак рубля за ночь -->
<span>24 682₽ за ночь</span>
</body>
Скринридер NVDA называет числа, но не озвучивает тысячи. Я предположил, что дело в пробеле. Поэтому убрал его.
<body>
<!-- NVDA. В браузерах Chrome и Firefox. Двадцать четыре тысячи шестьсот восемьдесят рубль за ночь -->
<!-- JAWS. В браузерах Chrome и Firefox. Два четыре шесть восемь два знак рубля за ночь -->
<span>24682₽ за ночь</span>
</body>
«Отлично!» — подумал я, когда протестировал этот код. А потом решил снова проверить скринридером JAWS и увидел, что он сломался, начав называть число по цифрам. Такое же поведение было на примере с миллионами.
<body>
<!-- NVDA. В браузерах Chrome и Firefox. Двадцать четыре шестьсот восемьдесят два девятьсот восемьдесят восемь рубль за ночь -->
<!-- JAWS. В браузерах Chrome и Firefox. Двадцать четыре миллиона шестьсот восемьдесят две тысячи девятьсот восемьдесят восемь знак рубля за ночь -->
<span>24 682 988₽ за ночь</span>
</body>
<body>
<!-- NVDA. В браузерах Chrome и Firefox. Двадцать четыре миллиона шестьсот восемьдесят две тысячи девятьсот восемьдесят восемь рубль за ночь -->
<!-- JAWS. В браузерах Chrome и Firefox. Два четыре шесть восемь два девять восемь восемь знак рубля за ночь -->
<span>24682988₽ за ночь</span>
</body>
Если мы разделяем разряды числа пробелом, то скринридер NVDA не может озвучить словесную альтернативу, т. е. тысячи, миллионы и т. д. А если не использовать пробел для разделения, то скринридер JAWS воспринимает число, как строку цифр.
Это ещё не все неприятности. Во втором эксперименте я использовал число «24 000».
<body>
<!-- NVDA. В браузерах Chrome и Firefox. Двадцать четыре ноль ноль ноль рубль за ночь -->
<!-- JAWS. В браузерах Chrome и Firefox. Двадцать четыре тысячи знак рубля за ночь -->
<span>24 000₽ за ночь</span>
</body>
<body>
<!-- NVDA. В браузерах Chrome и Firefox. Двадцать четыре тысячи рубль за ночь -->
<!-- JAWS. В браузерах Chrome и Firefox. Два четыре ноль ноль ноль знак рубля за ночь -->
<span>24000₽ за ночь</span>
</body>
Скринридер NVDA не только не озвучил тысячи, так ещё дополнительно начал озвучивать каждый ноль. Это поведение встречается всегда, когда в коде отделены нули пробелом. Если его нет, то озвучка становится естественной. Но в этом случае она ломается в скринридере JAWS.
Что можно сделать? Как я уже сказал, у меня нет рекомендуемого решения. У меня была идея создавать скрытую текстовую альтернативу для разрядов.
<body>
<!-- NVDA. В браузерах Chrome и Firefox. Двадцать четыре тысячи шестьсот восемьдесят два рубль за ночь -->
<!-- JAWS. В браузерах Chrome и Firefox. Двадцать четыре тысячи шестьсот восемьдесят два знак рубля за ночь -->
<span>24 <span class="visually-hidden" role="presentation">тысячи</span> 682₽ за ночь</span>
</body>
Я пока не протестировал это решение в продакшене. Поэтому используйте его, как идею для вдохновения. Если придумаете решение проблемы, поделитесь, пожалуйста, со мной.
▍ Заключение
С помощью этой статьи я с Ильёй хотел призвать вас:
- прорабатывать ссылки «Подробнее», чтобы они не являлись барьером для ваших пользователей;
- использовать явную связь элементов
<input>
и<label>
с помощью атрибутовid
иfor
при вёрстке нестандартных чекбоксов; - подумать, что можно сделать при вёрстке больших чисел.
Также нам будет интересен и ваш опыт. Делитесь своими кейсами в комментариях. Спасибо за чтение.
P.S. Если вы хотите больше узнать о цифровой доступности, пишите мне в ТГ. Ссылка в профиле.
P.P.S. Все статьи серии доступны по тегу html_css_a11y_story_melnik909.
© 2024 ООО «МТ ФИНАНС»
Telegram-канал со скидками, розыгрышами призов и новостями IT ?
artptr86
А вв не проверяли, как скринридеры будут читать суммы с неразрывным пробелом в качестве разделителя, а также отбитым пробелом знаком рубля?