Рубрики
Верстальщику Разработка

Проблемы доступности веб-форм

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

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

Общие проблемы

Группы полей в форме без fieldset и legend

Представьте себе ситуацию, в которой отдельные поля формы и лейблы повторяются, но каким-то образом визуально сгруппированы. Например, при заполнении формы для отправки посылки у вас могут быть поля «имя» и «адрес» как для отправителя, так и для получателя. Без fieldset и legend человек, использующий программу чтения с экрана, не сможет определить, какие поля предназначены для информации об отправителе, а какие — для получателя.

В такой ситуации нужно обязательно использовать тег fieldset для группировки полей и legend для того, чтобы озаглавить такую группу.

Пример правильного кода:

<fieldset>
  <legend>Данные отправителя</legend>

  <label for="sender-name">Имя</label>
  <input type="text" id="sender-name"> 

  <label for="sender-address">Адрес</label> 
  <input type="text" id="sender-address">
</fieldset>

<fieldset>
  <legend>Данные получателя</legend>

  <label for="recipient-name">Имя</label>
  <input type="text" id="recipient_name">

  <label for="recipient-address">Адрес</label>
  <input type="text" id="recipient-address">
</fieldset>

После отправки формы с ошибками фокус не устанавливается на первом элементе с ошибкой

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

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

Для этого лучше всего использовать “инлайн” валидацию форм. Если вы будете использовать все возможности HTML 5, и правильно указывать тип поля а также, что оно обязательно к заполнению, то вы уже будете иметь довольно неплохую доступность. Вот пример. Однако даже сегодня этот метод не будет работать на 100% хорошо во всех устройствах. Поэтому лучше взять контроль над этим в свои руки.

Непосредственно перед отправкой формы (или после AJAX ответа в случае серверной валидации) вы можете реализовать правильное поведение для невалидных полей.

Пример кода:

<form name="registration" id="form" action="contact.php" method="post" onsubmit="return validateform();">
        <div class="form-group">
            <div class="input-group col-xs-12 text-left">
                <label for="InputName">Полное имя:<span style="color:red;">*</span></label>
                <input type="text" name="name" id="InputName" class="form-control" placeholder="Имя">
                <br>
                <span id="f_error_msg"></span>
            </div>
        </div>
        <div class="form-group">
            <input type="submit" name="submit" class="btn btn-success btn-block" value="Отправить">
        </div>
    </form>
function validateform() {
var fullname = document.registration.name.value;

if (fullname === null || fullname === "") {
    resetErrorMsg();

    document.getElementById('f_error_msg').innerHTML = "Пожалуйста, введите полное имя";
    document.registration.name.focus();
    document.getElementById('f_error_msg').style.display = "block";
    return false;
}else{
    document.getElementById('f_error_msg').style.display = "none";
}
}

function resetErrorMsg(){
document.getElementById('f_error_msg').style.display = "none";
}

Описание поля не ассоциировано с самим полем

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

Чтобы связать описание с соответствующими полями, добавьте в поле формы атрибут aria-describedby, указывающий на идентификатор элемента, содержащего описание.

Обратите внимание, что тег <label> все равно нужен. Описания не заменяют лейблы полей!

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

<div id="general-instructions">Вы должны быть членом клуба, чтобы иметь возможность авторизоваться.</div>

<div class="form-field">
  <label for="username">Имя пользователя:</label>
  <input type="text" id="username" aria-describedby="username-instructions general-instructions">

  <div id="username-instructions" class="instructions">Имя пользователя не может содержать специальные символы.</div>
</div>

<div class="form-field">
  <label for="password">Пароль:</label>
  <input type="password" id="password" aria-describedby="password-instructions general-instructions">

  <div id="password-instructions" class="instructions">Пароль должен содержать минимум 8 знаков.</div>
</div>

Поля формы без лейблов или неверно связанные лейблы

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

Важно: атрибут placeholder не является лейблом и никогда не должен рассматриваться как альтернатива видимому лейблу.

Когда текст лейбла поля формы визуально присутствует рядом с полем, зрячие пользователи могут предположить, что лейбл связан с ближайшим видимым полем формы. Этот контекст, обеспечиваемый близостью лейблов, не очевиден для пользователей программ чтения с экрана, работающих в режиме форм/фокуса, поскольку программа чтения с экрана интерпретирует поля формы независимо от их лейблов. Если лейбл поля не связан должным образом с полем, программы чтения с экрана и другие вспомогательные технологии не будут определять взаимосвязь между элементами. Без ассоциации программы чтения с экрана не могут объявить ассоциированную метку при фокусировке поля в режиме форм/фокуса, а программное обеспечение распознавания голоса может быть не в состоянии идентифицировать поле, которое пользователь желает редактировать. Видимые лейблы для каждого поля должны быть правильно связаны с их полем формы с помощью атрибута for или путем инкапсуляции поля формы в элемент <label>.

Исключения

В редких случаях в некоторых полях формы может отсутствовать видимый лейбл, но все поля должны, как минимум, иметь лейбл со стилями только для чтения с экрана (visuallyhidden), связанный с полем. Для элементов select видимый лейбл не обязателен, если первый элемент option включает тот же или аналогичный текст, что и лейбл. Пример:

<select>
  <option value="">Область или район</option>
  ...
</select>

Решение

Назначьте <label> полю формы, включив атрибут for в тег label и соответствующий атрибут id в тег <input>.

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

<label for="name">Имя:</label>
<input type="text" id="name" name="name">

Альтернативное решение

Если поле визуально помечено иконкой или каким-либо другим нестандартным методом, и если использование элемента <label>, предназначенного только для чтения с экрана, невозможно, то можно использовать атрибуты aria-label или aria-labelledby. aria-label может содержать основной текст метки в значении атрибута.

<input type="text" name="name" aria-label="Имя">

aria-labelledby может содержать значение идентификатора элемента span или другого элемента, содержащего текст, подходящий для использования в качестве лейбла:

<img src="image.jpg" id="name" alt="Имя">
<input type="text" name="name" aria-labelledby="name">

Неправильные лейблы для полей даты рождения

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

Решение

  1. Убедитесь, что каждое поле (месяц, день и год) имеет правильно связанный с помощью атрибута for тег <label> и этот элемент видим на экране.
  2. Поместите все поля для даты рождения в  тег <fieldset> с <legend> «Дата рождения» в качестве первого дочернего элемента fieldset.
<fieldset>
  <legend>Дата рождения</legend>

  <label for="day">День</label>
  <select name="day" id="day">
    <option value="1">1</option>
    ...
  </select>

  <label for="month">Месяц</label>
  <select name="month" id="month">
    <option value="Январь">Январь</option>
    ...
  </select>

  <label for="year">Год</label>
  <select name="year" id="year">
    <option value="1947">1947</option>
    ...
  </select>
</fieldset>

Атрибут placeholder использован в качестве лейбла

Атрибут placeholder (плейсхолдер) для текстового поля поддерживается HTML5 с предполагаемой целью дать пользователю подсказку о том, какой тип содержимого следует вводить в это поле. Не следует полагаться только на текст этого атрибута для обозначения поля формы, потому что, когда поле получает фокус, текст атрибута исчезает. Пользователи с нарушениями памяти или когнитивных способностей могут быть не в состоянии вспомнить, для чего это поле. Это проблема не только тогда, когда пользователь активно набирает текст в поле, но и когда он пытается просмотреть свои ответы перед отправкой формы. Кроме того, плейсхолдеры могут создавать ненужные трудности для пользователей клавиатуры, которым необходимо перейти к полю, чтобы взаимодействовать с ним, обычно вызывая немедленное исчезновение текста-заполнителя.

Чтобы избежать всех этих проблем используйте стандартный HTML <label> и свяжите его с полем формы с помощью атрибута for.

Обязательные поля и валидация

Обязательные поля не обозначены

Сайты нередко используют иконки, звездочки, цвет или другие индикаторы для обозначения того, что поля формы являются обязательными. К сожалению, многие из этих индикаторов легко упускаются из виду или не распознаются программами чтения с экрана и их пользователями. Добавление атрибута required или aria-required = "true" необходимо для указания статуса обязательного поля.

Если поле формы включает визуальную индикацию, которая указывает на то, что поле обязательно к заполнению добавьте атрибут required к элементу. Менее предпочтительным, но приемлемым решением является использование атрибута aria-required="true", но, как и в большинстве случаев использования ARIA, если стандартный HTML поддерживает решение, нецелесообразно использовать ARIA для достижения того же результата. Однако, если проверка браузера нежелательна и обязательный атрибут не может быть использован, использование aria-required = "true" также приведет к тому, что программы чтения с экрана сообщают, что соответствующее поле является обязательным без дальнейшей проверки.

Значение звездочки не определено

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

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

Чтобы помочь пользователю разобраться со значением этого элемента нужно перед полями формы добавить текстовое описание которое будет пояснять значение звездочки:

<p>* обозначает обязательные поля</p>

<label for="name">*Имя</label>
<input type="text" id="name" required>

Обратите внимание на то, что расшифровка значения звездочки должна быть расположена перед всеми полями форма а не после них.  

Сообщение об ошибке не ассоциировано с соответствующим полем

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

Свяжите сообщение об ошибке с соответствующим полем формы с помощью атрибута aria-describedby. Атрибут aria-describedby принимает идентификатор (или список идентификаторов, разделенных пробелами, если его описывает более одного элемента) элемента, содержащего описание ошибки.

<label for="first-name">Имя</label>
<input type="text" id="first-name" aria-describedby="first-names-errors" required>
<div id="first-name-errors">Имя не может быть пустым.</div>

Селект

Изменение селекта сбрасывает фокус

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

Решение

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

<select>
  <option value="volvo">Volvo</option>
  <option value="saab">Saab</option>
  <option value="mercedes">Mercedes</option>
  <option value="audi">Audi</option>
</select>
<button type="button">Выбрать</button>

Обратите внимание, что после селекта есть кнопка, которая и будет запускать обработчик после изменения значения поля.

Селект без лейбла

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

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

Стандартный пример:

<label for="cars">Европейские машины</label>

<select id="cars">
  <option>Volvo</option>
  <option>Saab</option>
  <option>Mercedes</option>
  <option>Audi</option>
</select>

Альтернативный вариант:

Добавьте элемент option по умолчанию к элементу select, который включает тот же или подобный текст, что и предполагаемый лейбл:

<select id="cars">
  <option value=""> - Выберите европейскую машину - </option>
  <option>Volvo</option>
  <option>Saab</option>
  <option>Mercedes</option>
  <option>Audi</option>
</select>

Кастомные селекты не доступны

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

Если это возможно, всегда отдавайте предпочтение системным селектам перед кастомными решениями.

Если все-таки вы должны использовать кастомный селект, вам нужно будет вручную контролировать состояние ряда атрибутов ARIA с помощью JavaScript. Рассмотрите, пожалуйста в качестве основы реализацию от рабочей группы WAI-ARIA.

Чекбоксы и радио

Чекбоксы и радио без легенд

Когда у чекбоксов и радио отсутствуют условные обозначения, пользователям программ чтения с экрана очень сложно узнать, какие контролы соответствуют различным вопросам. Например, у вас может быть заголовок, в котором указано «Выберите свои интересы» с такими метками, как «Охота» и «Обеспечение доступности веб-сайтов». Хотя каждый из контролов может иметь связанные лейблы, без легенды пользователям программ чтения с экрана трудно понять, что они должны «Выбирать свои интересы».

Убедитесь, что каждый набор контролов заключен в <fieldset>, а первым элементом является <legend>, содержащий описание назначения этого набора контролов.

<fieldset>
  <legend>Выберите свои интересы</legend>

  <label for="hunting">Охота</label>
  <input type="checkbox" id="hunting" name="interest" value="hunting">

  <label for="accessible">Обеспечение доступности веб-сайтов</label>
  <input type="checkbox" id="accessible" name="interest" value="accessible">
</fieldset>

Исключением могут быть случаи, когда значения контролов четко указывают свое назначение, например, когда их значения представляют собой полные предложения вроде: «Да, я принимаю условия». и «Нет, я не принимаю условия». Эти типы переключателей не требуют тега <legend>.

Кастомные чекбоксы и радио

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

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

Отображается видимый <label>, который активирует скрытый чекбокс или радио-контрол, если он был правильно привязан с помощью атрибута for. Вот как должна выглядеть разметка:

<input type="radio" name="chicken" value="bantam" id="bantam" class="sr-only">
<label for="bantam">Курица</label>

Важно! Избегайте использования SVG, символов Юникода и эмодзи для стилизации!

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

Вот несколько прикладных статей на эту тему:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *