
Хабр, я снова пришёл к вам с практическими советами про доступность вместе с Ильёй. Мы показываем, как HTML и CSS могут улучшить или ухудшить её. Напоминаю, что Илья — мой незрячий знакомый, который помогает мне найти наши косяки в вёрстке.
Сегодня мы рассмотрим следующие аспекты:
- какие символы нужно пропускать в тексте для атрибута
alt
; - в какой ситуации атрибут
inert
может быть бесполезен; - как атрибут
maxlength
не позволил моей знакомой купить авиабилеты; - в чём польза свойства
border
в режиме высокого контраста дисплея.
Давайте начнём!
▍ Не все символы полезны для текста в атрибуте alt
Каждый раз сравнивая опыт взаимодействия зрячего и пользователя скринридера, удивляюсь, сколько существует нюансов. Например, знаки препинания. Могли вы представить, что они могут мешать? А они могут. Илья подтверждает.
«Зрячий пользователь на понимание знаков препинания тратит миллисекунды, потому что он видит их вместе со словами. А для пользователя скринридера каждый символ — это самостоятельное слово. Соответственно, ему приходится тратить в разы больше времени на изучение той же информации.
По этой причине я отключил озвучку пунктуации. Но включаю её, если при озвучке фрагмента текста мне стали интересны нюансы».
Где могут ждать проблемы? В подсказках, вставленных в атрибут alt
. Например, скринридер JAWS озвучит следующие символы: двоеточие, точку с запятой, кавычки и скобки. Скринридер NVDA по умолчанию не озвучивает эти символы, но он их учитывает при подсчёте символов при озвучке подсказки. Если символов будет больше ста, то текст разбивается на две части.
<body>
<img alt="Врываемся на каждую встречу команд, в курилке, на митапах и спрашиваем: «Давайте доступность сделаем?»" src="picture.webp">
</body>
NVDA сначала скажет: «Графика врываемся на каждую встречу команд в курилке на митапах и спрашиваем давайте доступность». А потом: «Графика сделаем». JAWS скажет: «Врываемся на каждую встречу команд в курилке на митапах и спрашиваем двоеточие кавычки открыты давайте доступность сделаем кавычки закрыты графика».
Чтобы так не происходило, нужно удалить двоеточие, кавычки и знак вопроса.
<body>
<img alt="Врываемся на каждую встречу команд, в курилке, на митапах и спрашиваем. Давайте доступность сделаем" src="picture.webp">
</body>
За один раз скринридеры скажут: «Врываемся на каждую встречу команд в курилке на митапах и спрашиваем давайте доступность сделаем». Ничего лишнего. Илья сказал, что смысл не только не пострадал, а наоборот ему стало проще воспринимать сообщение. Красота.
▍ Многообещающий атрибут inert
Для любителей цифровой доступности атрибут inert
был очень долгожданным. По крайней мере, для меня точно. Его задача заключается в том, чтобы отключить интерактивность у всех элементов, которые находятся внутри элемента с ним.
Я думал, что атрибут будет полезен при реализации замыкания фокуса внутри открытого модального окна. Раньше это было возможно только при помощи JavaScript. Поэтому я так ждал этот атрибут. Он бы очень сильно упростил мне жизнь.
К моему сожалению, итоговая реализация стала неоднозначной. Для пояснения своей точки зрения я покажу реализацию паттерна с помощью JavaScript. Рассмотрим пример модального окна из руководства «ARIA Authoring Practices Guide».
Нажму на кнопку «Add Delivery Address». После появления модального окна с помощью клавиши Tab
дойду до кнопки «Cancel».

Нажму снова клавишу Tab
. Приложение переносит меня в первое поле вводя «Street». Таким образом приложение замкнуло фокус.

Важный момент заключается в том, что на моём пути не было элементов интерфейса браузера, таких как адресная строка, кнопка «Обновить страницу» и др.
Я переделал эту демонстрацию с использованием атрибута inert
. Также дошёл с помощью клавиши Tab
до кнопки «Cancel».

Нажимаю ещё раз клавишу Tab
. Браузер переносит меня на первый элемент в панели браузера. У меня это кнопка «Обновить страницу».

И это ключевая разница между старым и новым подходом. На момент написания статьи мне не удалось найти единое решение в сообществе. Есть сторонники того, что элементы браузера не должны отображаться пользователю. Илья относится к ним:
«Модальное окно — это вспомогательный интерфейс с конкретным функционалом, ограниченным набором компонентов. Оно реализует простейший сценарий для пользователя, когда он зашёл, сделал и вышел. При навигации предпочитаю, чтобы скринридер не давал мне выйти за пределы интерфейса такого окна. Грубо говоря, оно должно быть словно огорожено забором. Гарантировать, что я не запутаюсь, попав в общие компоненты браузера. Например, адресную строку».
А есть люди, считающие, что элементы браузера должны быть доступны при открытом модальном окне.
«Пользователю скринридера и клавиатуры должно быть доступно всё то, что и зрячему пользователю с мышкой там, где это возможно. Соответственно, адресная строка браузера доступна для взаимодействия в открытом модальном окне? Тогда, по логике, она должна быть доступна».
Я ещё раз отмечу. На момент написания статьи нет одной точки зрения, являющейся правильной. Лично я склоняюсь к первой группе, в которой Илья. Поскольку первый паттерн встречается пользователям давно, то с большей вероятностью они к нему привыкли. По этой причине я избегаю использования атрибута inert
в своих проектах в этом случае.
▍ Как атрибут maxlength
помешал купить авиабилеты
При разработке форм мы уделяем большое внимание валидации. Навешиваем кучу атрибутов и всё такое. Среди них довольно часто встречаются атрибуты minlength
и maxlength
. Они ограничивают количество символов, которое можно использовать при вводе данных в поле.
Я перейду к примеру поля для заполнения фамилии на сайте крупной авиакомпании.
<body>
<!-- начало формы -->
<div class="input input--small-label">
<label class="input__label input__label--star" for="id_0.3849218691047045">
<div class="h-display--inline">Фамилия</div>
</label>
<div>
<div class="input__text">
<input type="text" class="input__text-input" maxlength="30" id="id_0.3849218691047045">
</div>
<!-- конец формы -->
</body>
В этом коде разработчики добавили атрибут maxlength
со значением 30
. Таким образом, фамилия пользователя должна быть 30 символов или меньше. Вроде всё нормально. Чего я тут прикопался?
При использовании атрибут maxlength
у нас появляется несколько важных ограничений. Первое, мы не можем ввести больше тридцати символов. Браузеры не позволят нам этого сделать, заблокировав ввода тридцать первого символа. Второе, при вставке данных из буфера обмена лишние символы обрежутся. К чему приводят эти ограничения в жизни.
Согласно нашему законодательству, после регистрации брака можно брать двойные фамилии. Они записываются через дефис. Когда люди с такими фамилиями хотят полететь в Пекин, то они не могут это сделать. Причина заключается в том, что их фамилия не подходит под требования разработчика, который сверстал это поле ввода.
Такая ситуация произошла у моей знакомой Оксаны. После замужества у неё стала фамилия «Михайличенкова-Павлюченкова». На латинице «Mikhailichenkova-Pavlyuchenkova». Оформляя авиабилеты, она вставила латинскую версию в соответствующее поле.

В итоге приложение обрезало последнюю букву, которая является тридцать первым символом. И всё. Валидация не проходила. Она не могла ввести правильно свою фамилию. Пришлось искать другое приложение для покупки билета. К счастью, не все делают так, и она смогла купить билет.
Такие жизненные казусы случаются, если неправильно использовать атрибут maxlength
. Надеюсь, они его уберут и люди смогут покупать билеты.
▍ Чем полезно свойство border
в режиме высокого контраста дисплея
При стандартном отображении интерфейса мы легко можем определить области страницы, используя цвет. А как быть, если у пользователя включён режим высокого контраста дисплея?
Да, интересный вопрос. В этом режиме цвета интерфейса будут трансформированы. С большой вероятностью границы областей будет сложнее понять. Для этого случая у меня есть лайфхак. Мы можем использовать свойство border
.
Для демонстрации я создал блок с текстом и протестировал его в обычном режиме и режиме высокого контраста в Windows.
<body>
<div class="infoblock">
<p>Внимание! Этот текст привлечет ваше внимание</p>
</div>
</body>
.infoblock {
padding: 16px;
background-color: #f7f1ff;
}

Поскольку значение #f7f1ff
свойства background-color
трансформируется в none
, то границы блока потерялись во втором случае. Решит эту проблему свойство border
. Оно отображается в режиме высокого контраста дисплея, поэтому мы можем сделать границы элемента.
Вместе со свойством нам понадобится установить значение transparent
в качестве цвета рамки. Так она не будет отображаться в обычном режиме. Ещё важно сохранить правильные размеры элемента. Для этого нужно не забыть вычесть толщину рамки из свойства padding
. Я буду использовать значение 1px
для свойства border
, поэтому вычту его из 16px
.
.infoblock {
padding: 15px;
background-color: #f7f1ff;
border: 1px solid transparent;
}


Мне кажется, получилось классно. Единственное, что мне не нравится, это использование единиц изменения px
для свойства padding
. Мне больше нравится rem
, потому что я люблю проектировать интерфейсы с учётом изменения размера текста в настройках браузера.
.infoblock {
--_infoblock-border-width: var(--infoblock-border-width, 1px);
padding: calc(1rem - var(--_infoblock-border-width));
background-color: #f7f1ff;
border: var(--_infoblock-border-width) solid transparent;
}
В этом коде я использую функции calc()
, чтобы вычесть толщину границы. Пользовательские свойства помогают не дублировать значение и легко изменять его в будущем.
Вы можете использовать ту версию, которая вам больше нравится. Главное, этот трюк подходит для стилизации важных областей и элементов управления. Пользуйтесь на здоровье!
▍ Заключение
С помощью этой статьи мы с Ильёй хотели призвать вас:
- Избегать использования определённых символов пунктуации в тексте для атрибута
alt
. - Хорошо подумать при использовании атрибутов
inert
иmaxlength
. - Использовать лайфхак со значением
transparent
для свойстваborder
для важных областей и элементов управления.
Также нам будет интересен и ваш опыт. Делитесь своими кейсами в комментариях. Спасибо за чтение.
P.S. Если вы хотите больше узнать о цифровой доступности, пишите мне в ТГ. Ссылка в профиле.
P.S.S. Все статьи серии доступны по тегу html_css_a11y_story_melnik909.
Скидки, итоги розыгрышей и новости о спутнике RUVDS — в нашем Telegram-канале ?
