Как незрячие работают с Web
Бывают ситуации, когда по тем или иным причинам воспользоваться мышкой невозможно. И многие люди знают, что с помощью Tab или Shift+Tab можно перемещать системный фокус по некоторым объектам в браузере: ссылкам, полям формы и т. д. Можно решить, что незрячие именно так и перемещаются по страницам, но это не соответствует действительности.
Незрячий в своей работе пользуется скринридером — программой, озвучивающей текст на экране. Она даёт дополнительные возможности для навигации по элементам интерфейса.
Стоит отметить, что почти вся навигация по вебу, кроме вышеозначенных Tab и Shift+Tab, не отображается визуально на экране, так как скринридеры представляют весь контент в виртуальном буфере. Фокус у буфера тоже виртуален, следовательно, невидим. Клавиатурные стрелки вверх-вниз перемещают по строкам, вправо-влево — по символам, Ctrl+Вправо, Ctrl+Влево — по словам. Здесь работают все клавиши навигации по тексту.
Представление контента
Скринридер представляет пользователю веб-контент в линейном виде — так, как описано в HTML. Например, на сайте ВКонтакте сверху находится панель уведомлений, аудиоплеер и настройки страницы. Читаются они первыми, но визуально находятся посередине экрана сверху. Затем идёт левое меню: новости, мессенджер, друзья, музыка, видео и т. д. Оно читается после уведомлений и настроек страницы, но находится уже левее. Скринридер же всё это представляет для наглядности сверху вниз по строчкам в том порядке, как описано в HTML.
Быстрая навигация
Перемещаться по контенту можно не только стрелками и Tab/Shift+Tab. В скринридере есть клавиши быстрой навигации, позволяющие перемещаться по элементам одного и того же типа: H/Shift+H позволит выбрать следующий либо предыдущий заголовок, K/Shift+K — следующую или предыдущую ссылку. С помощью горячих клавиш можно перемещаться по флажкам, кнопкам, ориентирам (главное содержимое страницы, дополнительное содержимое, меню, подвал, шапка), цитатам и многим другим элементам.
Именно поэтому так важно соблюдать правильную разметку. Она не только поможет в оптимизации сайта для поисковых роботов, но и обеспечит незрячих людей быстрой навигацией.
Распространённые баги доступности веб-контента
- Неподписанная кнопка
Пример из полной версии сайта ВКонтакте: не озвучивается ни одна кнопка управления звонком, кроме «Ответить» и «Отклонить». Кнопки «Завершить звонок», «Включить/Выключить микрофон», «Показать список участников» — всё это не подписано. Для того чтобы подписать кнопку, достаточно добавить на неё атрибут aria-label с названием кнопки.
2. Неразмеченные элементы веб-страницы
Бывают такие веб-страницы, где элементы не размечены семантически. Визуально кажется, что это кнопка, но с точки зрения HTML это обычный кликабельный div без роли. Такие баги встречаются в десктопном VK Messenger. Он написан на Electron и представлен как веб-страница. Именно поэтому мы рассматриваем его в этой статье. Из-за неправильной разметки, как уже было сказано выше, нельзя перемещаться по элементам с помощью быстрых клавиш навигации и в некоторых случаях даже активировать элементы с клавиатуры.
Чтобы побороть это, можно использовать aria роли: role="button", role="header" и другие. Но это не значит, что если мы добавим role="button", наш элемент автоматически станет кнопкой. Он по-прежнему не будет кликабелен и будет считаться кнопкой только для озвучивания скринридером. Чтобы элемент стал кликабельным с клавиатуры, желательно полностью переопределить его в коде страницы как кнопку: <button>Нажми меня</button>. Если совсем не хочется переопределять весь элемент, добавляем role="button" и onkeydown="Код действия". Но это плохая практика!
3. Неправильное применение атрибута aria-hidden
Атрибут aria-hidden нужен для того, чтобы скрывать из дерева доступности ненужные для скринридера веб-элементы: например, обилие картинок или иконок. Но иногда разработчики скрывают вполне нужные вещи, к примеру, всплывающее окно выбора реакций в новостной ленте ВКонтакте.
Что нужно скрывать?
Любые неинтерактивные элементы, которые не нуждаются в озвучке. Примером может послужить техническая информация вверху страницы сайта ВКонтакте: фрейм https://queuev4.vk.com/q_frame.php?7 вне страницы.
Что не нужно скрывать?
Исключением являются капчи. С капчей, вопреки сложившемуся мнению, незрячий человек тоже взаимодействует. Он может вывести её на скринридер, скопировать в буфер, отправить на распознавание боту. Следовательно, капчу не нужно скрывать.
Бывают случаи, когда зачем-то скрывают обёртку модальных диалогов с помощью aria-hidden, но дочерние элементы при этом открыты — данного атрибута на них нет. В итоге получается кроссбраузерный баг доступности: в Chrome элементы этого диалога доступны фокусом по Tab/Shift+Tab, в Firefox недоступны никак. Примером такой реализации служит полная версия Почты Mail.ru после входа или диалог входа на сайте платёжной системы QIWI.
Резюмирую: не стоит скрывать обёртки модальных окон.
- Недоступность состояния включено/отключено
Иногда разработчики забывают разметить флажок или кнопку с состоянием Вкл/Выкл. В итоге незрячий пользователь не знает, какое состояние у элемента, и ему приходится гадать, включён он или же нет. Примерами может послужить поведение в Баг-трекере ВКонтакте и разделах «Настройки», «Уведомления» сайта. Примечательна кнопка включения/выключения микрофона во время звонка в полной версии сайта. Помимо описанной выше ошибки с озвучиванием состояния, кнопка ещё и не подписана — здесь баг двойной.
Всегда размечайте флажки. Чем угодно! Или aria-pressed, или навешиванием роли checkbox с атрибутом aria-checked="true/false".
2. Недоступность обновляемого контента
Если на сайте есть динамически изменяемая часть страницы, например, субтитры в видео, таймер или оповещения, можно использовать live regions (интерактивные области), чтобы скринридер брал эти элементы во внимание. Сейчас субтитры в видео ВКонтакте не озвучиваются им ни автоматически, ни вручную. Подробнее о том, как применять live regions, можно почитать здесь.
3. Фокус скринридера не следует за скроллом экрана
Пример: в мессенджере ВКонтакте есть ответы. Если мы отвечаем, сверху в виде цитаты отображается сообщение, на которое мы ответили, а ниже располагается сам ответ. Цитируемое сообщение кликабельно, и при нажатии на него переписка скроллится до того сообщения, на которое мы ответили, но фокус скринридера остаётся на месте. Чтобы исправить эту проблему, необходимо использовать метод .focus() в JavaScript.
Для наглядности страница с примером, где фокус циклично перемещается по четырём элементам. А здесь подробно разбирается синтаксис самого метода .focus().
Статью подготовил Гриша Конзалаев, участник программы бета-тестирования VK Testers.