Как исправить нарушения role =»tablist» / role =»tab» Ax?

#html #accessibility #axe

Вопрос:

На нашей странице есть несколько вкладок со следующей структурой:

 <ul role="tablist">
  <li>
    <div role="tab" tabindex="0" aria-selected="true" aria-controls="id1">First tab content...</div>
  </li>
  <li>
    <div role="tab">Second tab content...</div>
  </li>
</ul>
 

Это приводит к двум нарушениям при выполнении тестов доступности Axe, а именно:
<li> elements must be contained in a <ul> or <ol> , и Certain ARIA roles must contain particular children (также обратное, что некоторым дочерним элементам нужны определенные родительские роли).

Я понимаю, что первое нарушение связано с tablist ролью, означающей, что <ul> больше не рассматривается как <ul> . Я не понимаю второго нарушения, поскольку спецификация не устанавливает, что элементы с role="tab" являются непосредственными дочерними элементами tablist .

Одним из возможных исправлений, которое предотвращает эти нарушения, было бы перейти role="tab" к <li> элементам. Проблема, однако, заключается в другом нарушении: Nested interactive controls are not announced by screen readers , предположительно, из-за того, что содержащееся <div> в нем является фокусируемым. Изменение этого на внешний <li> потребует целого ряда изменений js и css, поэтому это не простое исправление.

В какой степени это действительно нуждается в исправлении и каков наилучший подход?

Ответ №1:

Ax неверен. Спецификация для tab роли гласит:

Авторы ДОЛЖНЫ убедиться tab , что элементы с ролью содержатся в элементе с ролью или принадлежат tablist ему.

Акцент мой. Обратите внимание, что это говорит о том, что a tab должно содержаться в a tablist . Содержащийся в означает не прямого потомка, а скорее потомка.

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

«Принадлежащий элемент» — это любой DOM-потомок элемента, любой элемент, указанный как дочерний через aria-owns , или любой DOM-потомок принадлежащего дочернего элемента.

Итак, еще раз, пока tab является потомком a tablist (дочерний элемент, внук, правнук и т. Д.), То технически это допустимо, а ax неверно.

Теперь определение «owned» дает вам представление о том, как вы можете обойти ошибку axe, если нарушение вас беспокоит. Добавьте aria-owns в свой <ul> и укажите на tab элементы (ваши <div> ). Ваш исходный код будет проходить axe следующим образом:

 <ul role="tablist" aria-owns="foo1 foo2">
  <li>
    <div id="foo1" role="tab" tabindex="0" aria-selected="true" aria-controls="id1">First tab content...</div>
  </li>
  <li>
    <div id="foo2" role="tab">Second tab content...</div>
  </li>
</ul>
 

У вас все еще есть проблема с <li> не содержащимся в a <ul> . @graham рассмотрел эту часть. И я также согласен с @graham в том, что вы должны следовать практике разработки шаблона проектирования вкладок.

Комментарии:

1. Главный совет aria-owns , поскольку это отличное решение, чтобы заставить Axe перестать жаловаться и не выполнять с ним циклические циклы! 1

Ответ №2:

Ответ с вашей текущей настройкой заключается в удалении семантического значения из <li> .

 <ul role="tablist">
  <li role="none presentation">
    <div role="tab" tabindex="0" aria-selected="true" aria-controls="id1">First tab content...</div>
  </li>
  <li role="none presentation">
    <div role="tab">Second tab content...</div>
  </li>
</ul>
 

role="none presentation" удаляет все семантическое значение из <li> (так что думайте об этом как <div> сейчас).

Было бы предпочтительнее переместить все «на один уровень», чтобы сохранить порядок в DOM, поэтому лучшим решением может быть:

 <ul role="tablist">
  <li role="tab" tabindex="0" aria-selected="true" aria-controls="id1">
    First tab content...
  </li>
  <li role="tab">
     Second tab content...
  </li>
</ul>
 

Это будет работать, поскольку теперь вы изменили семантическое значение как the <ul> , так и the <li> , хотя для этого может потребоваться небольшая корректировка CSS.

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

В качестве альтернативы вы можете рассмотреть использование <button> элементов для создания вкладок, см. Пример tabs на W3 о том, как это структурировать.

Преимущество в том, что click обработчик можно использовать как для взаимодействия с мышью, так и с клавиатурой, потому что вы используете <button> .