Доступность — это не так просто

bp8xbihxhc8myerkbxbfhka0zka.jpeg

Привет, Хабр! В предыдущей статье я рассказывал о простых случаях проблем с доступностью, исправив которые можно сделать свой сайт или web-приложение гораздо доступнее. Я упоминал о правиле 80/20 и писал о проблемах, которые при наименьших затратах дают наибольший результат. Сегодня я бы хотел поговорить о другой группе проблем, которые входят в 20% и для решения которых нет готовых рецептов вроде «всегда заполняйте атрибут alt» или «используйте верные заголовки».

Выбирая формат повествования, я не придумал ничего лучше, чем просто описать ход своих мыслей на достаточно часто встречающемся примере.

Формализуем проблему


Как я уже говорил, для некоторых проблем в сфере доступности невозможно предложить какое-то простое решение. Эти проблемы очень вариативны, а иногда и вовсе уникальны для конкретного приложения. Помимо этого, ситуация осложняется различиями в работе разных скринридеров в разных браузерах и на разных операционных системах. Дополняет всё это то, что решение лежит на стыке двух дисциплин: доступности с её стандартами и Interaction Design (Проектирование взаимодействия) с её достаточно гибкими правилами.

Если вы, как и я в такие моменты, чувствуете уныние, то предлагаю не решать все проблемы сразу, а двигаться постепенно.

Обычно я начинаю с описания алгоритма взаимодействия с моим элементом для пользователей без мышки. Пользователи клавиатуры — это большая группа пользователей, далеко не всегда с какими-то ограничениями. Иногда это просто люди, которые ценят скорость работы.

Почти все сложные проблемы с доступностью возникают на элементах, которые динамически изменяют контент после какого-то действия пользователя.

К таким элементам можно отнести:

  • табы;
  • модальные окна;
  • аккордеон;
  • меню (в том числе с большой вложенностью).


Каждый компонент их этого списка можно условно разделить на две составляющие:

  • триггер — элемент, запускающий действие;
  • целевой контент — элемент, который содержит в себе кусочек видоизмененного контента.


Реализация триггера


Первое, с чем я предлагаю разобраться, — это какой базовый элемент будет лежать в основе триггера. Использование элементов, которые сразу являются фокусируемыми и интерактивными, я считаю хорошей идеей. Поэтому сразу отбрасываю всевозможные реализации с помощью div, span и т. д.

В итоге я прихожу к первому вопросу: должен ли быть триггер ссылкой или кнопкой?

Ответ на этот вопрос звучит примерно так: «в зависимости от ситуации», но в целом, вы не ошибётесь, если будете всегда использовать кнопку.

Кнопка — это элемент, предназначенный для запуска каких-либо интерактивных элементов внутри страницы. Поэтому пользователь, нажимая на кнопку, будет готов, что на странице что-то изменится. Кажется, это то, что нам нужно. Тем не менее, я считаю, что ссылки имеют некоторые преимущества в некоторых случаях.

Поэтому я задаю себе второй вопрос: должен ли изменившийся контент получить фокус?
И опять ответом на этот вопрос будет фраза «в зависимости от ситуации». Но можно помочь себе, просто посмотрев на DOM-дерево и оценив, насколько далеко триггер находится от целевого контента.

Если целевой контент находится сразу после триггера, то стоит использовать кнопку и обойтись без автоматического фокуса на целевой элемент. Поскольку пользователь следующим «табом» попадает на появившийся контент.


 

Target content.


Но если целевой контент находится на некотором расстоянии от активирующего его элемента, то, возможно, стоит посмотреть в сторону не очень модных, но отлично работающих гиперссылок с фрагментами.

Trigger Text

Target content.

Реальный пример


Предположим, в макете, предоставленном дизайнером, имеется элемент «Войти», расположенный в шапке сайта. И, согласно дизайну, по нажатию должно открыться модальное окно с формой входа. Сам код модального окна, скорее всего, находится в конце DOM-дерева. В этом случае использование ссылки не кажется мне плохой идеей.

При работе со ссылками, в отличие от кнопок, пользователь ожидает, что после клика он будет куда-то перенаправлен. И, в целом, модальные окна можно рассматривать как отдельные страницы, поэтому результат не будет неожиданным для пользователя.

Вернёмся к вопросам, поставленным выше:»Должен ли быть триггер кнопкой или ссылкой?» и «Должен ли фокус автоматически переключиться на целевой контент?» Ответ на эти вопросы можно найти, просто ответив на вопрос: «Как далеко друг от друга находятся триггер и целевой контент».

Далее я добавляю на страницу немного JavaScript, чтобы убедиться, что пользователи клавиатуры и мыши могут взаимодействовать с созданным компонентом. Конечно, не обходится без небольшой магии с tabindex и методом focus(), которые заслуживают отдельной статьи.

Теперь самое время подумать о пользователях скринридеров. Первое, что стоит сделать — это добавить атрибуты aria-expanded в триггер и aria-hidden в целевой контент.

// Таргет не активирован
Триггер - aria-expanded="false",
Целевой контент - aria-hidden="true".

// Пользователь нажал на таргет элемент
Триггер — aria-expanded=«true»,
Целевой контент — aria-hidden=«false».

Ещё существует атрибут aria-controls, который позволяет явно указать взаимосвязь между целевым компонентом и триггером.


Target content.


Правда, он не всегда работает так, как это можно ожидать.

В качестве заключения


Для более наглядного примера я реализовал два codepan: один с триггером в виде кнопки, а второй со ссылкой (кнопка, ссылка). В чём разница, спросите вы? Всё просто: в примере со ссылкой целевой контент сразу получил фокус без каких-то дополнительных телодвижений со стороны разработчика.

Это наводит меня на мысль, что, возможно, если вы работаете над SPA, то стоит задуматься, стоит ли делать SPA, а потом пытаться сделать его доступным, продумывая, куда перевести фокус в появившемся контенте. Где должен оказаться фокус после исчезновения появившегося контента, что будет с фокусом, когда целевой контент скроется? Ведь очень часто, пытаясь делать SPA доступным, вы во много повторяете функциональность, уже заложенную в браузеры.

В любом случае, я надеюсь, что эта небольшая прогулка на волне моих мыслей оказалась для вас полезной. Теперь вы знаете, как можно справиться с проблемами доступности, которые, на первый взгляд, кажутся неприступными.

И помните, что тот факт, что вы дочитали этот материал до конца, означает, что вы знаете, как решать проблемы с доступностью лучше, чем большинство разработчиков.

Спасибо за внимание, всем добра!

© Habrahabr.ru