Когда CSS недостаточно: требования к JavaScript для доступных компонентов

Опубликовано: 2022-03-10
Краткое резюме ↬ Внимание, спойлер: всплывающие подсказки, модальные окна, вкладки, карусели и раскрывающиеся меню — это некоторые из компонентов пользовательского интерфейса, для которых требуется нечто большее, чем CSS. Чтобы обеспечить доступность вашего интерфейса, JavaScript является необходимым дополнением для управления фокусом, реагирования на события клавиатуры и переключения атрибутов ARIA.

Как автор ModernCSS.dev, я большой сторонник CSS-решений. И мне нравится видеть, как умно люди используют CSS для действительно нестандартных дизайнов и интерактивности! Однако я заметил тенденцию к продвижению компонентов «только CSS» с использованием таких методов, как «взлом флажка». К сожалению, подобные взломы приводят к тому, что значительное количество пользователей не могут использовать ваш интерфейс.

В этой статье рассказывается о нескольких распространенных компонентах, а также о том, почему CSS недостаточно для обеспечения специальных возможностей путем подробного описания требований к JavaScript. Эти требования основаны на Руководстве по доступности веб-контента (WCAG) и дополнительных исследованиях, проведенных экспертами по доступности. Я не буду предписывать решения JavaScript или демонстрацию CSS, а скорее рассмотрю, что необходимо учитывать при создании каждого компонента. Фреймворк JavaScript, безусловно, можно использовать, но это не обязательно для добавления обсуждаемых событий и функций.

Перечисленные требования в целом не являются необязательными — они необходимы для обеспечения доступности ваших компонентов.

Если вы используете платформу или библиотеку компонентов, вы можете использовать эту статью, чтобы оценить, соответствуют ли предоставленные компоненты требованиям специальных возможностей . Важно знать, что многие из отмеченных элементов не будут полностью покрыты автоматическими инструментами тестирования доступности, такими как aXe, и поэтому требуют некоторого ручного тестирования. Или вы можете использовать среду тестирования, такую ​​как Cypress, для создания тестов для требуемой функциональности.

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

Еще после прыжка! Продолжить чтение ниже ↓

Определение того, является ли использование только CSS подходящим решением

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

  • Это для собственного удовольствия?
    Тогда полностью погрузитесь в CSS, раздвиньте границы и узнайте, на что способен этот язык!
  • Включает ли функция отображение и скрытие контента?
    Затем вам нужно, чтобы JS как минимум переключал арию и разрешал закрытие по Esc . Для определенных типов компонентов, которые также изменяют состояние, вам также может потребоваться сообщать об изменениях, инициируя обновления в активной области ARIA.
  • Является ли порядок естественной фокусировки наиболее идеальным?
    Если естественный порядок теряет связь между триггером и элементом, который он вызвал, или пользователь клавиатуры не может даже получить доступ к содержимому с помощью естественного порядка табуляции, тогда вам понадобится JS, чтобы помочь в управлении фокусом.
  • Предоставляет ли стилизованный элемент управления правильную информацию о функциональности?
    Пользователи вспомогательных технологий, таких как программы чтения с экрана, получают информацию на основе семантики и ARIA, которая помогает им определить, что делает элемент управления. Кроме того, пользователи системы распознавания речи должны иметь возможность идентифицировать метку или тип компонента, чтобы определить фразу, которая будет использоваться для управления элементами управления. Например, если ваш компонент оформлен как вкладки, но использует переключатели для «работы» как вкладки, программа чтения с экрана может услышать «переключатель», а пользователь речи может попытаться использовать слово «вкладка» для управления ими. В этих случаях вам понадобится JS, чтобы использовать соответствующие элементы управления и семантику для достижения желаемой функциональности.
  • Эффект зависит от наведения и/или фокуса?
    Тогда вам может понадобиться JS, чтобы помочь в альтернативном решении для обеспечения равного доступа или постоянного доступа к контенту, особенно для пользователей с сенсорным экраном и тех, кто использует масштабирование рабочего стола более 200% или программное обеспечение для увеличения.

Небольшой совет . Еще одним справочным материалом при создании любого вида настраиваемого элемента управления является Контрольный список разработки специальных возможностей пользовательского элемента управления из руководства W3 «Использование ARIA». Это упоминает несколько пунктов выше, с несколькими дополнительными соображениями по дизайну и семантике.

Подсказки

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

Примеры всплывающих подсказок от GitHub, Whimsical и Notion
Примеры всплывающих подсказок от GitHub, Whimsical и Notion. (Большой превью)

Решение, основанное только на CSS, здесь может показаться вполне приемлемым и может быть выполнено с помощью чего-то вроде:

 <button class="tooltip-trigger">I have a tooltip</button> <span class="tooltip">Tooltip</span> .tooltip { display: none; } .tooltip-trigger:hover + .tooltip, .tooltip-trigger:focus + .tooltip { display: block; }

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

Большая группа исключенных пользователей — это те, кто использует сенсорные экраны, где :hover , возможно, не будет запущен, поскольку на сенсорных экранах событие :hover запускается синхронно с событием :focus . Это означает, что любое связанное действие, связанное с триггерным элементом, таким как кнопка или ссылка, будет срабатывать вместе с отображаемой всплывающей подсказкой. Это означает, что пользователь может пропустить всплывающую подсказку или не успеть прочитать ее содержимое.

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

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

Руководство по поведению всплывающих подсказок взято из критерия успеха WCAG 1.4.13 — Контент при наведении курсора или фокусе. Этот критерий призван помочь пользователям с плохим зрением и тем, кто использует программы масштабирования и увеличения. Руководящие принципы для всплывающей подсказки (и другого контента, появляющегося при наведении и фокусе) включают:

  • Увольняемый
    Всплывающую подсказку можно закрыть без перемещения курсора или фокуса.
  • Hoverable
    Отображаемое содержимое всплывающей подсказки можно наводить, не исчезая
  • Настойчивый
    Дополнительный контент не исчезает по тайм-ауту, а ждет, пока пользователь удалит наведение или фокус, или иным образом отклонит его.

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

  • Пользователи вспомогательных технологий предполагают, что поведение при увольнении связано с клавишей Esc , для которой требуется прослушиватель JavaScript.
  • Согласно исследованию Сары Хигли, описанному в следующем разделе, добавление видимой кнопки «закрыть» во всплывающей подсказке также потребует JavaScript для обработки события закрытия.
  • Возможно, JavaScript может потребоваться дополнить ваше решение по стилю, чтобы пользователь мог наводить курсор на содержимое всплывающей подсказки, не закрывая ее, когда пользователь перемещает мышь.

Альтернативы всплывающим подсказкам

Всплывающие подсказки должны быть последним средством. Сара Хигли — эксперт по доступности, которая особенно любит отговаривать от использования всплывающих подсказок — предлагает этот простой тест:

«Почему я добавляю этот текст в интерфейс? Куда еще он мог деться?»

— Сара Хигли из презентации «Подсказки: расследование по четырем частям»

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

Если вы помните, что атрибут title существует, просто знайте, что он страдает теми же проблемами, которые мы заметили в нашем решении, основанном только на CSS. Другими словами — не используйте title , предполагая, что это приемлемое решение для всплывающей подсказки.

Для получения дополнительной информации ознакомьтесь с презентацией Сары на YouTube, а также с ее обширной статьей о всплывающих подсказках. Чтобы узнать больше о всплывающих подсказках и переключаемых подсказках, а также о том, почему не использовать title , просмотрите статью Хейдона Пикеринга из Inclusive Components: Tooltips and Toggletips.

Модальные

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

Примеры модальных окон из GitHub и Material Design
Примеры модальных окон с GitHub и Material Design. (Большой превью)

Я видел несколько вариантов модального окна только для CSS (и я виновен в том, что сделал один для более старой версии моего портфолио). Они могут использовать «флажковый хак», использовать поведение :target или попытаться создать его на основе :focus (который, вероятно, на самом деле является замаскированной слишком большой всплывающей подсказкой).

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

В отличие от всплывающих подсказок, модальные окна предназначены для структурированного контента. Это потенциально означает заголовок, некоторое содержимое абзаца и интерактивные элементы, такие как ссылки, кнопки или даже формы. Чтобы большинство пользователей могли получить доступ к этому контенту, они должны иметь возможность использовать события клавиатуры , особенно табуляцию. Для более длинного модального контента клавиши со стрелками также должны сохранять возможность прокрутки. И, как и всплывающие подсказки, их можно скрыть с помощью клавиши Esc — и нет возможности включить это только с помощью CSS.

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

Вот последовательность модальных связанных событий , которыми необходимо управлять с помощью JavaScript:

  1. Прослушиватель событий на кнопке открывает модальный
  2. Фокус находится внутри модального окна; какой элемент зависит от модального содержимого (см. дерево решений)
  3. Фокус остается внутри модального окна, пока не будет убран.
  4. Предпочтительно, чтобы пользователь мог закрыть модальное окно с помощью клавиши Esc в дополнение к специальной кнопке закрытия или деструктивному действию кнопки, такому как «Отмена», если требуется подтверждение содержимого модального окна.
    1. Если Esc разрешен, клики по модальному фону также должны закрыть модальное окно.
  5. После закрытия, если навигация не произошла, фокус возвращается на элемент триггерной кнопки.

Дерево решений модального фокуса

На основе примера модального диалогового окна WAI-ARIA Authoring Practices, здесь представлено упрощенное дерево решений для того, куда поместить фокус после открытия модального окна. Здесь выбор всегда будет диктоваться контекстом, и в идеале фокус управляется дальше, чем просто «первый фокусируемый элемент». На самом деле, иногда необходимо выбрать нефокусируемые элементы.

  • Первичным подлежащим модального глагола является форма.
    Фокус на первом поле формы.
  • Модальный контент значителен по длине и выталкивает модальные действия из поля зрения.
    Сосредоточьтесь на заголовке, если он есть, или на первом абзаце.
  • Назначение модального окна процедурное (пример: подтверждение действия) с несколькими доступными действиями.
    Сосредоточьтесь на «наименее разрушительном» действии в зависимости от контекста (пример: «ОК»).
  • Назначение модала – процедурное с одним действием.
    Сосредоточьтесь на первом фокусируемом элементе

Подсказка . В случае необходимости сфокусировать нефокусируемый элемент, например заголовок или абзац, добавьте tabindex="-1" , что позволит программно сфокусировать элемент с помощью JS, но не добавит его в порядок вкладок DOM. .

Обратитесь к модальной демонстрации WAI-ARIA для получения дополнительной информации о других требованиях для настройки ARIA и дополнительных сведений о том, как выбрать, к какому элементу добавить фокус. Демонстрация также включает JavaScript, чтобы проиллюстрировать, как управлять фокусом.

Для готового решения Китти Жиродель создала a11y-dialog, который включает в себя требования к функциям, которые мы обсуждали. Адриан Роселли также исследовал управление фокусом модальных диалогов, создал демонстрацию и собрал информацию о том, как различные комбинации браузера и программы чтения с экрана будут сообщать о сфокусированном элементе.

Вкладки

Интерфейсы с вкладками включают ряд триггеров, которые отображают соответствующие панели содержимого по одной за раз. «Хаки» CSS, которые вы можете найти для них, включают использование стилизованных переключателей или :target , которые позволяют открывать только одну панель за раз.

Примеры вкладок от Shopify Polaris и IBM Carbon
Примеры вкладок от Shopify Polaris и IBM Carbon. (Большой превью)

Вот функции вкладки, для которых требуется JavaScript:

  1. Переключение атрибута aria-selected на true для текущей вкладки и false для невыбранных вкладок
  2. Создание передвижного tabindex , чтобы отличать выбор вкладки от фокуса
  3. Перемещайте фокус между вкладками, реагируя на события клавиш со стрелками (и, возможно, Home и End ).

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

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

О tabindex

Концепция перемещаемого tabindex заключается в том, что значение tabindex программно контролируется для управления порядком фокуса элементов. Что касается вкладок, это означает, что только выбранная вкладка является частью порядка фокуса путем установки tabindex="0" , а для невыбранных вкладок устанавливается значение tabindex="-1" , что удаляет их из естественного порядка фокуса клавиатуры.

Причина этого в том, что при выборе вкладки следующая вкладка переместится в фокус пользователя на соответствующей панели вкладок. Вы можете сделать элемент, который является панелью вкладок, фокусируемым, назначив ему tabindex="0" , или это может быть необязательно, если есть гарантия фокусируемого элемента на панели вкладок . Если содержимое вашей панели вкладок будет более изменчивым или сложным, вы можете рассмотреть возможность управления фокусом в соответствии с деревом решений, которое мы рассмотрели для модальных окон.

Примеры шаблонов вкладок

Вот несколько эталонных шаблонов для создания вкладок:

  • Демонстрация Tabpanel от Университета Деке
  • Тесты виджетов вкладок от Скотта О'Хара (тестирует несколько функциональных шаблонов)
  • Интерфейсы с вкладками из Inclusive Components Хейдона Пикеринга, которые демонстрируют, как вкладки могут быть прогрессивным улучшением оглавления.

Карусели

Карусели, также называемые слайд-шоу или слайдерами, включают в себя серию вращающихся панелей контента (также называемых «слайдами»), которые включают механизмы управления. Вы найдете их во многих конфигурациях с широким спектром контента. Они несколько печально известны как плохой шаблон проектирования.

Пример демонстрации карусели, созданной с помощью bxSlider
Пример демонстрации карусели, созданной с помощью bxSlider. (Большой превью)

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

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

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

Ниже приведены рекомендации по использованию JavaScript в зависимости от функций карусели:

  • Использование элементов управления с разбивкой на страницы
    После выбора пронумерованного элемента программно сфокусируйте соответствующий слайд карусели. Это потребует настройки контейнеров слайдов с использованием перемещаемого tabindex, чтобы вы могли сфокусироваться на текущем слайде, но запретили доступ к слайдам за пределами экрана.
  • Использование автовоспроизведения
    Включите элемент управления паузой, а также включите паузу при наведении курсора на слайд или фокусе на интерактивном элементе внутри него. Кроме того, вы можете проверить наличие prefers-reduced-motion в JavaScript, чтобы загружать слайд-шоу в состоянии паузы, чтобы учесть предпочтения пользователя.
  • Использование предыдущих/следующих элементов управления
    Включите визуально скрытый элемент, помеченный как aria-live="polite" , и после активации этих элементов управления заполните живую область указанием текущей позиции, например «Слайд 2 из 4».

Ресурсы для создания доступных каруселей

  • Тщательные сведения и рекомендации по реализации, а также полный пример кода из руководства W3C по веб-доступности на каруселях.
  • Пример Университета Деке по преобразованию интерфейса вкладок в карусель
  • Пример авторской практики WAI-ARIA карусели изображений с автоматическим вращением
  • Подборка карусельных ресурсов в обзоре доступных компонентов Smashing.

Выпадающие меню

Это относится к компоненту, в котором кнопка открывает список ссылок, обычно используемых для меню навигации. Реализации CSS, которые останавливаются на отображении меню при :hover или :focus , упускают только некоторые важные детали.

Примеры выпадающих меню из Dribbble, поиска Google и GitHub
Примеры выпадающих меню из Dribbble, поиска Google и GitHub. (Большой превью)

Признаюсь, я даже думал, что с помощью более нового свойства :focus-within мы могли бы безопасно реализовать решение, основанное только на CSS. Вы увидите, что моя статья о выпадающих меню CSS была изменена, чтобы включить примечания и ресурсы по необходимому JavaScript (я сохранил название, чтобы другие, ищущие это решение, также могли завершить реализацию JS). В частности, использование только CSS означает нарушение критерия успеха WCAG 1.4.13: Контент при наведении курсора или фокусе, о котором мы узнали из всплывающих подсказок.

Нам нужно добавить JavaScript для некоторых методов, которые на данный момент должны показаться вам знакомыми:

  • Переключение aria-expanded на кнопке меню между true и false путем прослушивания событий click
  • Закрытие открытого меню при использовании клавиши Esc и возврат фокуса на кнопку переключения меню
  • Предпочтительно закрытие открытых меню при перемещении фокуса за пределы меню.
  • Необязательно : используйте клавиши со стрелками, а также клавиши Home и End для навигации с помощью клавиатуры между кнопками переключения меню и ссылками в раскрывающихся списках.

Подсказка : убедитесь в правильности реализации раскрывающегося меню, связав отображение меню с селектором .dropdown-toggle[aria-expanded= " true " ] + .dropdown вместо того, чтобы основывать отображение меню на наличии дополнительного JS- добавлен класс как active . Это также устраняет некоторую сложность вашего JS-решения!

Это также называется «шаблоном раскрытия», и вы можете найти более подробную информацию в меню навигации «Пример раскрытия информации» WAI-ARIA Authoring Practices.

Дополнительные ресурсы по созданию доступных компонентов

  • Полное руководство Smashing по доступным внешним компонентам
  • Статья Кэри Фишер «Хорошо, лучше, лучше всего: распутывая сложный мир доступных шаблонов»
  • Демонстрации и информация об общих шаблонах проектирования и виджетах доступны в WAI-ARIA Authoring Practices 1.2.
  • Кодовая библиотека Университета Деке
  • Доступные компоненты Скотта О'Хара
  • Инклюзивные компоненты Хейдона Пикеринга