什么是符合WAI-ARIA标准的导航栏/菜单实现?

42

我们正在将 WAI-ARIA 支持添加到 Web 门户网站的主导航菜单中,即此处显示的菜单:

Navigation menu screenshot

菜单是通过经典的 <ul> / <li> / <a> DOM 树实现的,使用 CSS 进行样式设计,使其看起来像水平选项卡。

如何实现符合 WAI-ARIA 的此类小部件?

我阅读了 w3org 最近的 WAI-ARIA 规范的许多部分,以便对其进行一般理解、分类等等。然后,我阅读了几个 UI 小部件实现的示例。我找不到任何专门针对此类 CSS 导航菜单的示例。我始终找到的最接近的小部件是菜单、菜单栏和选项卡面板。当然,我也在 Free ARIA Community group(这个问题最初发布的地方)中寻找过。

我会说,这些小部件中没有一个完全符合(CSS)导航菜单的要求。例如,TabPanel 可能会控制页面中的某些内容(--> aria-controls),可能还有 MenuBar;但我并不确定导航菜单是否控制页面中的内容(它控制下一页要显示的内容)。未深入了解之前,还有一些其他差异。 参考文献在帖子末尾。如果有更好(或更适合)的导航菜单示例,我们将很高兴了解。
5个回答

76

一个可能的实现方式如下:

HTML结构:

<div> <!-- Outer wrapper -->
  <ul> <!-- Main navigation bar container -->
    <li> <!-- First-level item without submenu -->
      <a> <!-- Destination URL -->
      </a>
    </li>
    <li> <!-- First-level item with submenu -->
      <a> <!-- Destination URL -->
      </a>
      <ul> <!-- Second-level menu container -->
        <li> <!-- Second-level item -->
          <a>
          </a> <!-- Destination URL -->
        </li>
      </ul>
    </li>
  </ul>
</div>

角色:

  • 在外层包装器<div>上使用role =“navigation”
  • 在导航栏容器<ul>上使用role ="menubar"
  • 在第二级<ul>容器上使用role="menu"
  • 在第一和第二级菜单项的<li>上使用role="presentation"(它们不需要在公开的可访问菜单栏结构中)
  • 在第一和第二级<a>菜单项上使用role="menuitem"

属性:

  • 对于具有子菜单的第一级<a>菜单项,使用aria-haspopup="true"
  • 对于第二级<ul>容器,使用aria-labelledby="前一个<a>菜单项的ID"

状态:

  • 对于当前访问的第一或第二级<a>项目使用aria-selected="true";其他<a>项目则为aria-selected="false"。这是为了强制执行“已选== >当前页面”的概念
  • 对于第二级<ul>容器,使用aria-expanded="true/false"
  • 对于第二级<ul>容器,使用aria-hidden="true/false"
  • 对于主要的<ul>导航栏容器,使用aria-activedescendant=""。这是与tabindex一起使用的替代方法
  • 对于当前访问的<a>项,使用tabindex=0;其他<a>项目,则使用tabindex=-1。这是为了在定位到导航栏时首先聚焦于当前页面。这是与aria-activedescendant一起使用的替代方法

键盘:

  • Tab:从Web应用程序中的其他点移动焦点进/出菜单。
  • Shift+Tab:以相反的顺序从Web应用程序中的其他点移动焦点进/出菜单。
  • 右箭头:下一个导航栏项目
  • 左箭头:上一个导航栏项目
  • Enter:激活当前聚焦的项(即导航到相应的URL)
  • 空格:激活当前聚焦的项(即导航到相应的URL)

Aug/2014: aria-selected Vs menuitem

回复@Joshua Muheim的评论:现在我可以从这里以及从他的参考文献中看到,aria-selected属性不允许用于menuitem角色。
根据当前的情况,如我从这个最近的SO答案中阅读的那样,有一些解决方案,还有一个新的建议属性。


3
在阅读到你的答案之前,我差不多要放弃对"Aria规范"的想法了。对我而言,我在菜单中缺少的是“presentation”角色,这导致了奇怪的行为,比如每个菜单项都被读出为“1 of 1”而不是“1 of [length]”。大多数我在网上看到的例子都会导致这种不良行为,除了你的回答,我没有找到任何一个说ul[role=menu]>li[role=presentation]>a[role=menuitem]的例子。做得好! - Iain Fraser
很高兴它有帮助!就我所知,xxx [role = presentation] 的需要仅出现在您仅出于美学目的插入某些(嵌套)节点时,即定位、显示/隐藏、背景着色等。但是那些节点从内容角度来看毫无意义,因此您可以为任何辅助工具标记它们。 - superjos
最近的更新:规格现在以更加“开发者友好”的方式编写,正如http://html5doctor.com/using-aria-in-html中所说。 - superjos
我认为aria-selected不能用于aria菜单。http://www.w3.org/TR/wai-aria/states_and_properties#aria-selected 这似乎是一个常见的错误,我不知道更好的方法来指示所选状态,除了添加一些视觉上隐藏的文本,如“活动项目”。 - Joshua Muheim
1
如果某些顶级菜单项不是链接,而只是用于打开子菜单的按钮,应该如何处理? - jbyrd
显示剩余7条评论

0
ARIA设计模式为一系列自定义控件提供了预期的UI行为http://www.w3.org/TR/wai-aria-practices/#aria_ex,在桌面和Web上,使用esc键关闭并返回触发元素是标准UI。可以在任何Google文档应用程序(例如)中尝试它。

0

通过将具有role=menuitem的元素添加aria-posinsetaria-setsize属性,您可以获得一个菜单来宣布“X of Y”信息。


谢谢分享。我认为如果菜单DOM动态变化,这可能对其他人有所帮助。我可以从这里阅读到:“如果集合中的所有元素都存在于DOM中,则不需要”。 - superjos
这更像是一条评论而不是一个答案。 - TylerH

-1

点击“ESC”键关闭是一个历史悠久的标准,许多用户都希望使用这种方式。


这更像是一条评论而不是一个答案。 - TylerH

-1

+按下“Esc”键应该关闭打开的菜单并将焦点返回到打开它的元素。


我已经有一段时间没有考虑那些功能了。乍一看,使用Escape键关闭打开的菜单似乎是一个不错的选择(我不记得在我的搜索中是否已经提到过)。然而,我不确定在使用Esc关闭菜单后应该发生什么:你的建议(将焦点返回到打开它的元素)对我来说似乎不太合适。 - superjos
1
转义是一种标准的关闭方式。http://access.aol.com/dhtml-style-guide-working-group/#menu - user810937
这更像是一条评论而不是一个答案。 - TylerH

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接