Я создал пользовательский Nav Walker для WordPress, чтобы добавить соответствующие роли ARIA к выводу wp_nav_menu()
функция. Это хорошо. Но я застрял, пытаясь сделать две вещи.
Мой ходок выдает следующий вывод:
<nav id="siteNav" role="navigation">
<ul id="menuMain" class="menu" role="menubar">
<li id="menu-item-1698" class="menu-item" role="presentation">
<a href="http://localhost/" role="menuitem">Front Page</a>
</li>
<li id="menu-item-1697" class="menu-item" role="presentation">
<a href="http://localhost/blog/" role="menuitem">Blog</a>
</li>
<li id="menu-item-1694" class="menu-item" role="presentation">
<a href="http://localhost/sample-page/" role="menuitem">Sample Page</a>
</li>
<li id="menu-item-1695" class="menu-item" role="presentation">
<a href="http://localhost/page-b/" role="menuitem">Page B</a>
</li>
<li id="menu-item-1696" class="menu-item" role="presentation">
<a href="http://localhost/page-a/" role="menuitem">Page A</a>
</li>
<li id="menu-item-1699" class="menu-item" role="presentation">
<a href="http://localhost/" role="menuitem">Front Page</a>
</li>
<li id="menu-item-1701" class="menu-item" role="presentation">
<a href="http://localhost/level-1/" role="menuitem">Level 1</a>
<ul class="sub-menu" role="menu" aria-expanded="false">
<li id="menu-item-1702" class="menu-item" role="presentation">
<a href="http://localhost/level-1/level-2b/" role="menuitem">Level 2b</a>
</li>
<li id="menu-item-1703" class="menu-item" role="presentation">
<a href="http://localhost/level-1/level-2a/" role="menuitem">Level 2a</a>
</li>
<li id="menu-item-1704" class="menu-item" role="presentation">
<a href="http://localhost/level-1/level-2/" role="menuitem">Level 2</a>
<ul class="sub-menu" role="menu" aria-expanded="false">
<li id="menu-item-1705" class="menu-item" role="presentation">
<a href="http://localhost/level-1/level-2/level-3b/" role="menuitem">Level 3b</a>
</li>
<li id="menu-item-1706" class="menu-item" role="presentation">
<a href="http://localhost/level-1/level-2/level-3a/" role="menuitem">Level 3a</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
То, что я пытаюсь сделать сейчас, это добавить какой-то идентификатор в <a>
элементы являются братьями и сестрами в <ul class="sub-menu">
элементы и ссылки на этот идентификатор в aria-labelledby
имущество.
Таким образом, пункт меню, содержащий подменю, будет выглядеть следующим образом:
<li id="menu-item-1704" class="menu-item" role="presentation">
<a href="http://localhost/level-1/level-2/" role="menuitem" id="{ID}">Level 2</a>
<ul class="sub-menu" role="menu" aria-expanded="false" aria-labelledby="{ID}">
<li id="menu-item-1705" class="menu-item" role="presentation">
<a href="http://localhost/level-1/level-2/level-3b/" role="menuitem">Level 3b</a>
</li>
<li id="menu-item-1706" class="menu-item" role="presentation">
<a href="http://localhost/level-1/level-2/level-3a/" role="menuitem">Level 3a</a>
</li>
</ul>
</li>
Код для моего ходунка:
класс Walker_ARIA_Nav_Menu расширяет Walker {
public $tree_type = array( 'post_type', 'taxonomy', 'custom' );public $db_fields = array( 'parent' => 'menu_item_parent', 'id' => 'db_id' );public function start_lvl( &$output, $depth = 0, $args = array() ) {
$indent = str_repeat( "\t", $depth );
$output .= "\n$indent<ul class=\"sub-menu\" role=\"menu\" aria-expanded=\"false\" aria-hidden=\"true\">\n";
}public function end_lvl( &$output, $depth = 0, $args = array() ) {
$indent = str_repeat( "\t", $depth );
$output .= "$indent</ul>\n";
}public function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
$indent = ( $depth ) ? str_repeat( "\t", $depth ) : '';
$classes = empty( $item->classes ) ? array() : (array) $item->classes;
$classes[] = 'menu-item-' . $item->ID;$args = apply_filters( 'nav_menu_item_args', $args, $item, $depth );
$class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item, $args, $depth ) );
$class_names = $class_names ? ' class="' . esc_attr( $class_names ) . '"' : '';
$id = apply_filters( 'nav_menu_item_id', 'menu-item-'. $item->ID, $item, $args, $depth );
$id = $id ? ' id="' . esc_attr( $id ) . '"' : '';
$output .= $indent . '<li' . $id . $class_names .' role="presentation">';
$atts = array();
$atts['title'] = ! empty( $item->attr_title ) ? $item->attr_title : '';
$atts['target'] = ! empty( $item->target ) ? $item->target : '';
$atts['rel'] = ! empty( $item->xfn ) ? $item->xfn : '';
$atts['href'] = ! empty( $item->url ) ? $item->url : '';$atts = apply_filters( 'nav_menu_link_attributes', $atts, $item, $args, $depth );
$attributes = '';
foreach ( $atts as $attr => $value ) {
if ( ! empty( $value ) ) {
$value = ( 'href' === $attr ) ? esc_url( $value ) : esc_attr( $value );
$attributes .= ' ' . $attr . '="' . $value . '"';
}
}$title = apply_filters( 'nav_menu_item_title', $title, $item, $args, $depth );
$item_output = $args->before;
$item_output .= '<a'. $attributes .' role="menuitem">';
$item_output .= $args->link_before . $title . $args->link_after;
$item_output .= '</a>';
$item_output .= $args->after;$output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
}public function end_el( &$output, $item, $depth = 0, $args = array() ) {
$output .= "</li>\n";
}
} // End Walker_ARIA_Nav_Menu Class
Я собираюсь ответить на это в предположении, что вы создаете это меню для веб-сайта или аналогичного (не приложение, которое вы устанавливаете на выбранной вами ОС, которое должно вести себя так же, как меню родной ОС).
При этом, я полагаю, у вас есть общая проблема ARIA, которая делает PHP частью вашего вопроса спорным.
Сразу же, учитывая следующий HTML-код, который вы предлагаете:
<ul class="sub-menu" role="menu" aria-expanded="false" aria-labelledby="{ID}">
<li id="menu-item-1705" class="menu-item" role="presentation">
<a href="http://localhost/level-1/level-2/level-3b/" role="menuitem">Level 3b</a>
</li>
<li id="menu-item-1706" class="menu-item" role="presentation">
<a href="http://localhost/level-1/level-2/level-3a/" role="menuitem">Level 3a</a>
</li>
</ul>
… вы должны просто пропустить aria-labelledby
, Поскольку на этом элементе нет табуляции (я не имею в виду tabindex
), у программы чтения с экрана нет причин объявлять об этом, так что не будет. Кроме того, если это сделал есть табуляция, aria-labelledby
переопределяет доступное имя, которое могло бы быть в этом элементе. Изо рта лошади:
Заданное поведение aria-labelledby заключается в том, что соответствующий текст метки объявляется вместо текста ссылки (не в дополнение к тексту ссылки). Когда сам текст ссылки должен быть включен в текст метки, идентификатор ссылки должен также указываться в строке идентификаторов, формирующих значение атрибута aria-labelledby.
Теперь поговорим обо всем подходе. Я рекомендую вам не использовать role="menu"
ни role="menuitem"
здесь вообще. Используя их, можно ожидать от пользователя программы чтения с экрана, что все меню будет вести себя как строка меню в его / ее ОС. Я не знаю, подготовили ли вы все необходимое взаимодействие с клавиатурой, чтобы сделать это правдой, но по моему опыту такое случается редко.
Если вы не согласны со мной, вот несколько источников для обзора …
Виджеты меню должны обеспечивать поддержку клавиатуры для навигации по всем пунктам меню в меню. Поддержка клавиатуры для меню обычно включает в себя клавиши курсора для перемещения между пунктами меню и открытия и закрытия всплывающих меню.
Затем он описывает все взаимодействия с клавиатурой, которые вам понадобятся для сопоставления, и предоставляет блок примера HTML. Вы можете заметить, что он не использует атрибуты ARIA, которые вы используете так, как вы их используете.
Такое меню появляется на Список рассылки WebAIM регулярно. Вот выдержка из одна из многих дискуссий:
Но чтобы сделать шаг назад, может быть в первую очередь полезно убедиться, что ARIA
менубар на самом деле уместно. Это обычно не подходит для
навигация по сайту — предназначена для строки меню веб-приложения
(подумайте «Файл …», «Редактировать …» и т. д.).
Если вы посмотрите на современное состояние в доступных меню, то это доступное мега-меню от Adobe, вы увидите, что Adobe явно указывает, почему он не использует role="menu"
ни role="menuitem"
:
Мы не используем
role="menu"
для контейнера меню иrole="menuitem"
для каждой из этих ссылок, потому что если мы это сделаем, вспомогательные технологии больше не будут интерпретировать ссылки как ссылки, а вместо этого как элементы меню, и ссылки в нашей глобальной навигации больше не будут отображаться, когда пользователь программы чтения с экрана выполняет ярлык Команда, чтобы вызвать список ссылок на странице.
Наконец, я призываю вас создать статическую HTML-версию вашего идеального меню, а затем протестировать ее с помощью программы чтения с экрана. Вы можете получить копию NVDA для Windows бесплатно (хотя Вы действительно должны пожертвовать), и VoiceOver предустановлен на Mac.
Как в сторону, WordPress имеет форум поддержки, посвященный доступности, так что вы также можете спросить там.
Чтобы добавить к этому обсуждению, есть несколько вещей, которые вы можете прочитать. Во-первых, немного истории о том, почему группа доступности WordPress не может обеспечить доступность в раскрывающихся списках внешнего интерфейса, поскольку есть некоторые ресурсы. Смотрите это обсуждение: Сделать клавиатуру выпадающего меню доступной Во-вторых, рассмотрите возможность изучения кода, используемого в одной из тем WordPress по умолчанию (например, 2015 или 2016), поскольку эти темы готовы к доступности и включают раскрывающиеся меню. В-третьих, доступность вашего внешнего интерфейса зависит не только от самого PHP, но и от вашего JavaScript. Это потому, что вам нужно убедиться, что ваше меню доступно с клавиатуры, прежде чем Aria появится на экране.
Аманда