Хабр, я снова пришёл к вам с практическими советами про доступность вместе с Ильёй. Мы показываем, как HTML и CSS могут улучшить или ухудшить её. Напоминаю, что Илья мой незрячий знакомый, который помогает мне найти наши косяки в вёрстке.
Сегодня мы рассмотрим следующие аспекты:
- Какое количество символов следует использовать для текста подсказки для атрибута
alt
; - В чём польза атрибута
lang
; - Почему использование текстовых символов для декоративных задач — это плохая идея;
- Для чего существует режим повышенной контрастности.
Давайте начнём!
▍ Время перестать писать поэмы в атрибуте alt
Моё первое открытие в теме цифровой доступности был атрибут alt
. Это было, как будто вчера. Я слушал подкаст. Там говорили, что атрибут помогает узнать больше информации об изображении пользователям скринридера.
Естественно, у меня зародилась мысль писать очень подробный текст, стараясь описать каждую деталь.
<body>
<img src="eiffel-tower.webp" alt="Эйфелева башня расположена рядом с рекой, через которую перекинут мост. Вдоль моста выстроились лодки">
</body>
Хорошо, что я познакомился с людьми, использующие скринридеры повседневно. Они рассказали мне, что такие подсказки не просто не помогают, а они вредят.
«Во-первых, человек, использующий скринридер, получает очень много звуковой информации, особенно если находится за компьютером долго в течение дня. Представь. Вся навигация, все тексты, все буквально телодвижения озвучиваются. Когда ещё сверху ложится много информации о внешнем виде, да ещё красочнонаписанной, она минимум не улавливается пользователем.
А максимум, она жутко раздражает. Человеку нужно знать, что там за картинка, но буквально в двух словах. Как результат — излишняя когнитивная нагрузка и ненужная информация. А человек старался, писал...»
Кроме человеческих ограничений, существуют особенности скринридера. Мой первый скринридер был JAWS. Он зачитывает подсказки сразу польностью без дополнительных нажатий. Что не скажешь о NVDA.
У него есть ограничение по максимальному количеству символов, озвученных за раз. 100 символов. По этой причине, чтобы пользователь смог услышать подсказку «Эйфелева башня расположена рядом с рекой, через которую перекинут мост. Вдоль моста выстроились лодки» ему нужно сделать несколько нажатий на клавишу ↓
. Также из-за превышения лимита он услышит слово «Графика» два раза.
Исправить эту особенность можно только одним способом. Сократить текст, чтобы он был меньше 100 символов.
<body>
<img src="eiffel-tower.webp" alt="Эйфелева башня. Вид с реки Сены">
</body>
Скринридер NVDA скажет только один раз: «Графика. Эйфелева башня. Вид с реки Сены». Также замечу, что сами точки озвучены не будут, но скринридер делает паузу на их месте.
▍ Атрибут lang
подсказывает скринридерам язык текста
Атрибут lang
один из главных помощников скринридеров. Он подсказывает им, как правильно озвучить текст. Обычно стандарты требуют от нас его добавления для элемента <html>
. Если это не сделать, то код будет невалидный.
Для примера объявлю, что русский язык, основной на странице.
<html lang="ru">
К счастью, большинство разработчиков знают этот пример. Но я бы не добавил рассказ про атрибут, если бы не было сложностей. А они есть. Например, текст может быть озвучен некорректно. Как так получается?
Есть ситуации, когда для страницы указан один язык, а в тексте используются слова на другом.
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Пример использования атрибута lang</title>
</head>
<body>
<p>
Олимпи́йский комите́т Росси́и (англ. Russian Olympic Committee) — организация, представляющая страну в международном олимпийском движении
</p>
</body>
</html>
Скринридерам при озвучке фразы «Russian Olympic Committee» будет сложно. Они поймут, что она не на русском языке. По этой причине фраза будет звучать с акцентом, с неправильным ударением.
Исправить это может атрибут lang
. С помощью него мы укажем язык, на котором написан отрывок текста. Например, я обвернул фразу «Russian Olympic Committee» элементом <span>
с атрибутом lang
и значением en
, поскольку она на английском.
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Пример использования атрибута lang</title>
</head>
<body>
<p>
Олимпи́йский комите́т Росси́и (англ. <span lang="en">Russian Olympic Committee</span>) — организация, представляющая страну в международном олимпийском движении
</p>
</body>
</html>
Скринридер начинает озвучку текста одним голосом, установленного для русского языка. Дойдя до части текста, написанного на английском, переключится на голос для английского языка и озвучит её. Потом снова переключится на голос для русского языка и озвучит остаток текста.
▍ Текстовые символы для декоративных задач — это спам
Недавно я смотрел видео с заголовком, в котором использовалась буква «х», в качестве визуального разделителя.
<body>
<h1>Будаков х Подшибякина х Биги х Тарасов | Плохие Футболисты</h1>
</body>
Для зрячего пользователя в таком тексте нет проблем. Он пропустит букву «х» и символ «|», прочитав «Будаков», «Подшибякина», «Биги», «Тарасов», «Плохие Футболисты». А пользователи скринридера так сделать не могут. В итоге у них будет озвучен другой текст.
NVDA скажет: «Заголовок перового уровня. Будаков ха Подшибякина ха Биги ха Тарасов Плохие Футболисты.» Получается, буква «х» озвучивается, как «ха». Зачем тут «ха»? Не понятно. Единственный плюс в том, что символ вертикальной черты игнорируется по умолчанию.
В скринридере JAWS текст будет другой. Пользователи услышит: «Будаковх Подшибякинах Бигих Тарасовх вертикальная черта Плохие Футболисты. Заголовок перового уровня». Мне особенно понравилось Подшибякинах. Да, было бы смешно, если бы не так грустно.
Скринридер не понял, что буква «х» используется, как графический элемент. Присоеденил к словам, идущими перед ним. Вертикальная черта тоже озвучена, но это больше особенного самого скринридера. По умолчанию он озвучивает все символы, а не избирательно, как делает NVDA.
Что можно сделать с этой проблемой? Во-первых, на этапе написания текста постараться не использовать определённые символы, в качестве оформления. К ним относятся: «/», «#», «*», «$» и «&». Они озвучиваются скринридером, как: «косая черта», «решётка», «звёздочка», «доллар» и «амперсанд».
Во-вторых, если не получилось сделать первое, то надо скрыть символы. Атрибут aria-hidden
нам поможет.
<body>
<h1>Будаков <span aria-hidden="true">х</span> Подшибякина <span aria-hidden="true">х</span> Биги <span aria-hidden="true">х</span> Тарасов <span aria-hidden="true">|</span> Плохие Футболисты</h1>
</body>
В этом случае скринридеры скажут: «Будаков Подшибякина Биги Тарасов Плохие Футболисты». Разница в том, что NVDA в начале произнесёт «Заголовок перового уровня», а JAWS в конце.
▍ Режим повышенной контрастности. Что за зверь?
Яндекс провёл исследование о настройках доступности в Яндекс Браузер для iOS и Android. Оказывается, у 2% пользователей, или почти 850 000 человек, включён высокий контраст дисплея. Данный режим позволяет сделать текст более ярким по сравнению с фоном, повысив его разборчивость. В каких ситуациях потребуется данная настройка?
Например, пользователь открыл приложение на ярком солнце и ничего не видит из-за отблесков. Увеличив контрастность, он может лучше рассмотреть текст. Или интерфейс использует пользователь старшего возраста или слабовидящий. Люди данной группы видят текст расплывчато. Они используют контраст, чтобы сделать текст на экране более разборчивым.
Как этот режим влияет на веб-интерфейсы? Когда пользователь активирует режим, то браузеры принудительно добавляет стили на этапе отрисовки интерфейса, изменяя все свойства, задающие цвет.
Ещё устанавливается значение none
для свойств box-shadow
и text-shadow
, значение light dark
для свойства color-scheme
, значение auto
для свойства scrollbar-color
. Также значение none
устанавливается для свойства background-image
, за исключением случаев объявления функции url()
.
У нас есть определённые возможности работы с режимом. В CSS существует специальная медиа-функция forced-colors
со значением active
, помогающая написать стили для этого режима, если это требуется.
@media (forced-colors: active) {
/* здесь стили, применяемые в режиме высокой контрастности */
}
Дополнительно мы можем запретить браузерам трансформировать стили для определённого элемента. Нужно использовать свойство forced-color-adjust
и значение none
.
<body>
<div class="container">Этот элемент будет изменён</div>
<div class="container non-forced">Этот элемент не будет изменён</div>
</body>
.container {
border: 5px solid red;
background-color: #ccc;
}
.non-forced{
forced-color-adjust: none;
}
Я хочу предупредить, что свойство forced-color-adjust
не нужно повсеместно использовать. Это приведёт к проблемам. Лучше сразу написать стили так, чтобы они корректно работали в режиме повышенной контрастности.
▍ Заключение
С помощью этой статьи я с Ильёй хотел призвать вас:
- Стараться держать текст подсказки для атрибута
alt
размером до 100 символов; - Обворачивать элементом с атрибутом
lang
слова, если они написаны на языке, который отличается от основного; - Не использовать текстовые символы для декоративных задач или скрыть их с помощью атрибута
aria-hidden
; - Проверить интерфейс в режиме повышенной контрастности.
Оставлю ссылки на все выпуски:
Также нам будет интересен и ваш опыт. Делитесь своими кейсами в комментариях. Спасибо за чтение.
Автор: Стас Мельников